Начиная с TypeScript 2.8, мы можем получить тип 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
) и в R
возвращаемый типконструктор (=> infer R
, это будет тип экземпляра класса).
Используя A
и R
, мы можем определить требуемую функцию с типом возвращаемого значения R
, и мы распространяем аргументы конструктора на аргументы функции ((...a: A) => R
)