Я думаю, вы можете либо сказать Typescript, что superclass
может new
, синтаксис для которого кратко упоминается в руководстве по TypeScript :
// "new (...args: any[]) => any" means the constructor takes any number of arguments
// and returns anything
function nameableSubclassOf<C extends new (...args: any[]) => any>(superclass: C) {
return class extends superclass implements INameable {
name?: string = name
}
}
Это должно позволить компилятору выводить полезный, но довольно непрозрачный тип для возвращаемого значения nameableSubclassOf
:
const NameableFoo = nameableSubclassOf(Foo)
// const NameableFoo: {
// new (...args: any[]): nameableSubclassOf<typeof Foo>.(Anonymous class);
// prototype: nameableSubclassOf<any>.(Anonymous class);
// } & typeof Foo ?
const nameableFoo = new NameableFoo();
// const nameableFoo: nameableSubclassOf2<typeof Foo>.(Anonymous class) & Foo; ?
const fooName = nameableFoo.name;
// const fooName: string | undefined; ?
... или, если вы хотите более явный тип, который не 'Если вы полагаетесь на анонимные классы, вы можете использовать обобщенные значения для указания суперкласса и условные типы для извлечения аргумента конструктора и возврата из него типов:
function nameableSubclassOf<C extends new (...args: any[]) => any>(
superclass: C
): C extends new (...args: infer A) => infer T ? new (...args: A) => T & INameable : never;
function nameableSubclassOf(
superclass: new (...args: any[]) => any
): new (...args: any[]) => INameable {
return class extends superclass implements INameable {
name?: string = name
}
}
Обратите внимание, что я использовал один перегрузка для сигнатуры вызова функции, которую видит вызывающая сторона.Сигнатура реализации более свободна, потому что компилятору сложно проверить, что значение присваивается условному типу ... поэтому перегрузка одной сигнатурой - это способ повысить безопасность типов для вызывающей функции без необходимости использоватьзагружает утверждений типа в реализации.
Это более многословно, но когда вы используете его, вы получаете более приятные типы:
const NameableFoo = nameableSubclassOf(Foo)
// const NameableFoo: new () => Foo & INameable ?
const nameableFoo = new NameableFoo()
// const nameableFoo: Foo & INameable ?
const fooName = nameableFoo.name
// const fooName: string | undefined ?
Надеюсь, один из нихпомогает.Удачи!