如何设置工厂函数以实现它在Typescript中生成的类的参数调用签名?

时间:2018-12-12 22:55:22

标签: javascript typescript dependency-injection decorator aurelia

我什至不确定我想做什么。我使用的框架提供了用于依赖项注入的装饰器,正确键入以下代码示例非常麻烦:

class Control {
  constructor(
    options: {
      tabIndex?: number
    },
    callbacks: {
      onChange?: (event: any) => void,
    }
  ) {
  
  }
}

@inject(Factory.of(Control))
class Form {
  public GetControl: any;
  public control: Control;
  
  constructor(GetControl: any) {
    this.GetControl = GetControl;
  }
  build() {
    this.control = this.GetControl({tabIndex: 0}, null);
  }
}

有没有一种方法可以设置GetControl的类型,而不必像下面这样在控件类中重复参数定义:

public GetControl: (
    options: {
      tabIndex?: number
    },
    callbacks: {
      onChange?: (event: any) => void,
    }
  ) => Control;

1 个答案:

答案 0 :(得分:1)

从TypeScript 2.8开始,我们可以使用休息参数(读取here)和条件类型(docs)中的元组从类中获取GetControl的类型。

class Control {
  constructor(
    options: {
      tabIndex?: number
    },
    callbacks: {
      onChange?: (event: any) => void,
    }
  ) {

  }
}

// Create a function with the same return type and parameters as a constructor
type Factory<T extends new (...a: any[]) => any> =
  T extends new (...a: infer A) => infer R ? (...a: A) => R : never;

class Form {
  ;
  public control: Control;
  // Shorthand field definition, same as your code but shorter :)
  constructor(public GetControl: Factory<typeof Control>) {
  }
  build() {
    this.control = this.GetControl({ tabIndex: 0 }, null);
  }
}

类型Factory将构造函数转换为具有相同参数的函数。我们这样做的方法是使用条件类型的推断行为。如果T扩展了构造函数类型(由于类型约束而这样做),我们要求编译器在A中放入一个包含所有参数类型(...a: infer A)和{的元组。 {1}}构造函数的返回类型(R,这是类实例类型)。

使用=> infer RA可以定义所需的函数,返回类型为R,然后将构造函数的参数扩展到函数的参数({{1} })