考虑 TypeScript 文档中泛型的最后一个示例: https://www.typescriptlang.org/docs/handbook/generics.html#using-class-types-in-generics
如果我想设置Lion默认值createInstance()我该怎么做?
例如:
class Animal {
numLegs: number = 0;
}
class Lion extends Animal {
keeper = "zookeeper";
}
function createInstance<A extends Animal>(c: new () => A = Lion): A { // error!
// -------------------------------------> ~~~~~~~~~~~~~~~~~~~~~
// 'Lion' is assignable to the constraint of type 'A', but 'A' could be
// instantiated with a different subtype of constraint 'Animal'.
return new c();
}
Run Code Online (Sandbox Code Playgroud)
目前还没有办法通过编译器验证的类型安全来做到这一点。有关相关功能请求,请参阅microsoft/TypeScript#56315 。目前所有的方法都涉及解决这个限制。
您可以使用泛型参数默认值和类型断言来告诉编译器缺乏推断意味着is A,并且可以做出该假设:ALion
function createInstanceAssert<A extends Animal = Lion>(c: new () => A = Lion as any) {
return new c();
}
Run Code Online (Sandbox Code Playgroud)
我认为这将在您的用例中按需要工作:
createInstanceAssert(Lion).keeper.nametag;
createInstanceAssert(Bee).keeper.hasMask;
createInstanceAssert().keeper.nametag;
Run Code Online (Sandbox Code Playgroud)
尽管有人可能手动指定通用参数并造成麻烦:
createInstanceAssert<Bee>().keeper.hasMask.valueOf(); // compiles, but error at runtime
// ---------------> ~~~~~ don't do this, okay?
Run Code Online (Sandbox Code Playgroud)
这可能不太可能,但您应该意识到这一点。
如果您确实想防止误用,可以使用重载来区分两个单独的用例:
function createInstanceOverload<A extends Animal>(c: new () => A): A;
function createInstanceOverload(): Lion;
function createInstanceOverload(c: new () => Animal = Lion) {
return new c();
}
Run Code Online (Sandbox Code Playgroud)
您基本上可以使用参数调用它,在这种情况下它是通用的并且A是推断的,或者您可以不带参数调用它,在这种情况下它不是通用的,并且Lion出现:
createInstanceOverload(Lion).keeper.nametag;
createInstanceOverload(Bee).keeper.hasMask;
createInstanceOverload().keeper.nametag;
Run Code Online (Sandbox Code Playgroud)
由于没有通用的零参数调用签名,因此在没有大编译器错误的情况下不再可能执行以下操作:
createInstanceOverload<Bee>().keeper.hasMask.valueOf(); // error at compile time
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5005 次 |
| 最近记录: |