为何TypeScript在约束混入场景下未抛出TS2339属性不存在错误?
问题原因分析
你的代码里访问未定义属性a不触发TS2339错误,核心原因在于混入函数的泛型约束过于宽泛,导致动态生成的类被隐式赋予了任意索引签名:
- 混入函数
withBindable的泛型约束是T extends new (...args: any[]) => any,这里的any意味着BaseType的实例类型被推断为any。当子类继承自这个BaseType时,TypeScript会默认认为该子类可以拥有任意属性,相当于自动添加了[key: string]: any的索引签名,因此访问this.a不会触发属性不存在的错误,且this.a的类型被推断为any。 - TypeScript对动态生成的类(即通过函数返回的继承类)的类型推断存在限制:如果父类的类型不够明确(比如用了
any),编译器无法为动态子类生成精确的类型校验规则,只能放宽限制允许任意属性访问。
修复方案
要让编译器严格检查未定义属性,需要收紧混入函数的泛型约束,避免使用any作为实例类型:
// 将泛型约束从 `=> any` 改为 `=> object`,明确实例类型为非any的对象 export function withBindable<T extends new (...args: any[]) => object>(BaseType: T) { return class extends BaseType { public mixin = 1; }; } class Base{ public b = 2; } class A extends withBindable(Base){ public test(){ this.mixin = 2; // OK this.b = 3; // OK this.a = 2; // 此时会触发TS2339错误:Property 'a' does not exist on type 'A' } }
或者如果需要更精确的约束,可以指定BaseType的实例必须符合某个接口,比如:
interface BaseInstance { b: number; } export function withBindable<T extends new (...args: any[]) => BaseInstance>(BaseType: T) { return class extends BaseType { public mixin = 1; }; }
这样编译器就能精确校验子类的属性,访问未定义的a时会正常触发错误。
内容的提问来源于stack exchange,提问作者cloud
相关产品推荐
相关产品推荐

