假设我们有以下代码:
class Foo<T = number> {
foo: T;
constructor(foo: T) {
this.foo = foo;
}
}
const F: typeof Foo<number> = Foo;
let f: unknown;
if (f instanceof F) {
f.foo; // 'any', why is this not a 'number'?
}
Playground
为什么f
的类型是Foo<any>
而不是Foo<number>
?我可以只使用instanceof
来实现吗?还是必须使用类型 predicate 函数?
3条答案
按热度按时间uelo1irk1#
你可以使用打字机防护装置,例如
pxq42qpu2#
通过检查
f instanceof F
来假定f
是Foo<number>
类型是不安全的。instanceof
运算符不关心泛型,因为它们在运行时被擦除。我们可以用
new Foo("a string")
示例化f
而不会出现问题。f instance F
将返回true
,即使f
的类型是Foo<string>
。检查
f
是否为Foo<number>
的 * 唯一 * 安全方法是使用类型保护,它同时检查f
是否为instanceof Foo
和typeof f.foo === "number"
。Playground
doinxwow3#
正如@TobiasS.和@MuratKaragöz所指出的,
instanceof
运算符在运行时不能区分Foo
和F
,因此泛型不会被传递下去。有两种方法可以解决此问题:
仅使用instanceof
我们可以创建一个新的构造函数类型,它返回
Foo<number>
的一个示例,而不是像我那样用typeof Foo<number>
来输入F
:或者我们也可以创建一个新的类
F
来扩展Foo<number>
(这可能是最安全的,因为F
在运行时不能与Foo
不匹配):使用类型保护
参见@ Tobias S.和@MuratKaragöz的答案。