Constructor overload in TypeScript

前端 未结 16 1987
滥情空心
滥情空心 2020-11-28 00:42

Has anybody done constructor overloading in TypeScript. On page 64 of the language specification (v 0.8), there are statements describing constructor overloads, but there wa

相关标签:
16条回答
  • 2020-11-28 01:21

    Here is a working example and you have to consider that every constructor with more fields should mark the extra fields as optional.

    class LocalError {
      message?: string;
      status?: string;
      details?: Map<string, string>;
    
      constructor(message: string);
      constructor(message?: string, status?: string);
      constructor(message?: string, status?: string, details?: Map<string, string>) {
        this.message = message;
        this.status = status;
        this.details = details;
      }
    }
    
    0 讨论(0)
  • 2020-11-28 01:22

    TypeScript allows you to declare overloads but you can only have one implementation and that implementation must have a signature that is compatible with all overloads. In your example, this can easily be done with an optional parameter as in,

    interface IBox {    
        x : number;
        y : number;
        height : number;
        width : number;
    }
    
    class Box {
        public x: number;
        public y: number;
        public height: number;
        public width: number;
    
        constructor(obj?: IBox) {    
            this.x = obj && obj.x || 0
            this.y = obj && obj.y || 0
            this.height = obj && obj.height || 0
            this.width = obj && obj.width || 0;
        }   
    }
    

    or two overloads with a more general constructor as in,

    interface IBox {    
        x : number;
        y : number;
        height : number;
        width : number;
    }
    
    class Box {
        public x: number;
        public y: number;
        public height: number;
        public width: number;
    
        constructor();
        constructor(obj: IBox); 
        constructor(obj?: any) {    
            this.x = obj && obj.x || 0
            this.y = obj && obj.y || 0
            this.height = obj && obj.height || 0
            this.width = obj && obj.width || 0;
        }   
    }
    
    0 讨论(0)
  • 2020-11-28 01:23

    Actually it might be too late for this answer but you can now do this:

    class Box {
        public x: number;
        public y: number;
        public height: number;
        public width: number;
    
        constructor();
        constructor(obj: IBox);
        constructor(obj?: IBox) {    
            this.x = !obj ? 0 : obj.x;
            this.y = !obj ? 0 : obj.y;
            this.height = !obj ? 0 : obj.height;
            this.width = !obj ? 0 : obj.width;
        }
    }
    

    so instead of static methods you can do the above. I hope it will help you!!!

    0 讨论(0)
  • 2020-11-28 01:25

    I know this is an old question, but new in 1.4 is union types; use these for all function overloads (including constructors). Example:

    class foo {
        private _name: any;
        constructor(name: string | number) {
            this._name = name;
        }
    }
    var f1 = new foo("bar");
    var f2 = new foo(1);
    
    0 讨论(0)
  • 2020-11-28 01:27

    I use the following alternative to get default/optional params and "kind-of-overloaded" constructors with variable number of params:

    private x?: number;
    private y?: number;
    
    constructor({x = 10, y}: {x?: number, y?: number}) {
     this.x = x;
     this.y = y;
    }
    

    I know it's not the prettiest code ever, but one gets used to it. No need for the additional Interface and it allows private members, which is not possible when using the Interface.

    0 讨论(0)
  • 2020-11-28 01:28

    Regarding constructor overloads one good alternative would be to implement the additional overloads as static factory methods. I think its more readable and simple than checking for all possible argument combinations at the constructor. Here is a simple example:

    function calculateAge(birthday): number {
      return new Date().getFullYear() - birthday;
    }
    
    class Person {
      static fromData(data: PersonData): Person {
        const { first, last, birthday, gender = 'M' } = data;
        return new this(
          `${last}, ${first}`,
          calculateAge(birthday),
          gender,
        );
      }
    
      constructor(
        public fullName: string,
        public age: number,
        public gender: 'M' | 'F',
      ) {}
    
      toString(): string {
        return `Hello, my name is ${this.fullName} and I'm a ${this.age}yo ${this.gender}`;
      }
    }
    
    interface PersonData {
      first: string;
      last: string;
      birthday: string;
      gender?: 'M' | 'F';
    }
    
    
    const personA = new Person('Doe, John', 31, 'M');
    console.log(personA.toString());
    const personB = Person.fromData({
      first: 'Jane',
      last: 'Smith',
      birthday: '1986',
      gender: 'F',
    });
    console.log(personB.toString());
    

    Method overloading in TypeScript isn't for real, let's say, as it would require too much compiler-generated code and the core team try to avoid that at all costs. Currently the main reason for method overloading to be present on the language is to provide a way to write declarations for libraries with magic arguments in their API. Since you'll need to do all the heavy-lifting by yourself to handle different sets of arguments I don't see much advantage in using overloads instead of separated methods.

    0 讨论(0)
提交回复
热议问题