使用instanceof为何无法推导泛型类类型?如何解决?
TypeScript instanceof 类型推导问题解析
代码示例
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,为什么不是number? }
为什么推导成 Foo?
TypeScript 里 instanceof 的类型收窄逻辑,只认构造函数的原型链,不管你给变量标注的类型是什么。
你给 F 标注了 typeof Foo<number>,但 F 实际指向的还是原始的 Foo 类构造函数。而泛型类的构造函数本身是泛型的,typeof Foo<number> 只是你给 F 加的类型约束,并没有真的把这个构造函数的实例类型锁死成 Foo<number>。
当用 instanceof F 判断时,TypeScript 只能识别出这是 Foo 类的实例,没法从 F 的类型标注里提取出泛型参数 number,所以就默认用了 Foo<any>。
怎么解决?
- 直接用原始类判断:如果不用变量
F,直接写f instanceof Foo,TypeScript 会自动用Foo的默认泛型参数number,推导结果就是Foo<number>,f.foo类型就是number。 - 用类型谓词函数:如果必须用
F来判断,就得自己写个类型谓词函数,明确告诉 TypeScript 判断成功后的类型:function isFooNumber(obj: unknown): obj is Foo<number> { return obj instanceof F; } if (isFooNumber(f)) { f.foo; // 这里类型就是number了 } - 创建绑定泛型的子类(不推荐):你可以建一个固定了泛型参数的子类,这样
instanceof就能识别正确类型,但会多一个子类,没必要的话不建议这么做:class FooNumber extends Foo<number> {} const F = FooNumber; if (f instanceof F) { f.foo; // 类型为number }
总结
只靠 instanceof 加标注了泛型的构造函数变量,没法推导出 Foo<number>,要么直接用原始泛型类,要么用类型谓词函数。
内容的提问来源于stack exchange,提问作者Anatole Lucet
相关产品推荐
相关产品推荐

