对此没有语言支持,如果这种情况足够普遍,我们能做的最好的事情就是推出我们自己的类创建函数,它对我们添加到类中的成员施加限制。
使用noImplicitThis
编译器选项,ThisType
我们也可以对类成员进行很好的类型检查,我们没有得到任何像明确的字段分配这样的花哨的东西,但它已经足够好了:
interface IDog {
bark(): void
}
function createClass<TInterfaces, TFields = {}>() {
return function<TMemebers extends TInterfaces>(members: TMemebers & ThisType<TMemebers & TFields>) {
return function<TCtor extends (this: TMemebers & TFields, ...a: any[]) => any>(ctor: TCtor) : FunctionToConstructor<TCtor, TMemebers & TFields> {
Object.assign(ctor.prototype, members);
return ctor as any;
}
}
}
const Dog = createClass<IDog, { age: number }>()({
eat() {
// this is not any and has the fields defined in the TFields parameter
// and the methods defined in the current object literal
for(let i =0;i< this.age;i++) {
this.bark();
console.log("eat")
}
},
bark() {
console.log("BA" + "R".repeat(this.age) + "K");
}
})(function(age: number) {
this.age = age; // this has the fields and members previously defined
this.bark();
})
const p = new Dog(10);
p.bark();
// Helpers
type IsValidArg<T> = T extends object ? keyof T extends never ? false : true : true;
type FunctionToConstructor<T, TReturn> =
T extends (a: infer A, b: infer B) => void ?
IsValidArg<B> extends true ? new (p1: A, p2: B) => TReturn :
IsValidArg<A> extends true ? new (p1: A) => TReturn :
new () => TReturn :
never;
注意上面的实现类似于这里的答案,你可以在那里阅读更深入的解释。