Search code examples
typescriptdry

Typescript noob question about having an parameter object with default props in class constructor


I have a javascript class that I want to rewrite to TS:

class A {
  constructor({foo = 'foo', bar = 123, baz = true} = {}) {
    this.foo = foo
    this.bar = bar
    this.baz = baz
  }
}

What that I currently wrote on TS:

interface AProps {
  foo: string,
  bar: number,
  baz: boolean,
}

class A {
  foo: string
  bar: number
  baz: boolean

  constructor({foo = 'foo', bar = 123, baz = true}: Partial<AProps> = {}) {
    this.foo = foo
    this.bar = bar
    this.baz = baz
  }
}

As you can see, typescript has 3 times more code, how to do this more compact? As I know, almost any code duplication is anti-pattern so there must be the way to tell typescript that I want all fields in class from that interface.


Solution

  • You don't need to specify AProps interface to hint type of the constructor, it will be inferred correctly.

    class A {
      foo: string
      bar: number
      baz: boolean
    
      constructor({foo = 'foo', bar = 123, baz = true} = {}) {
        this.foo = foo
        this.bar = bar
        this.baz = baz
      }
    }
    

    Constructor has type:

    constructor A({ foo, bar, baz }?: {
        foo?: string | undefined;
        bar?: number | undefined;
        baz?: boolean | undefined;
    }): A
    

    const a = new A({x: 1}); fails to compile with a message

    Argument of type '{ x: number; }' is not assignable to parameter of type '{ foo?: string | undefined; bar?: number | undefined; baz?: boolean | undefined; }'.
      Object literal may only specify known properties, and 'x' does not exist in type '{ foo?: string | undefined; bar?: number | undefined; baz?: boolean | undefined; }'.(2345)
    

    With original code

    constructor has type:

    constructor A({ foo, bar, baz }?: Partial<AProps>): A
    

    const a = new A({x: 1}); fails to compile with a message

    Argument of type '{ x: number; }' is not assignable to parameter of type 'Partial<AProps>'.
      Object literal may only specify known properties, and 'x' does not exist in type 'Partial<AProps>'.(2345)