TypeScript 类类型兼容:为何公共成员不校验继承层级?
TypeScript 类类型兼容性规则与相关疑问
文档明确的兼容性判定逻辑
根据TypeScript的类型系统设计约定:
- 类中的
private私有成员、protected受保护成员会直接影响类型兼容性判定 - 只要类包含这类非公共成员,就只有声明来源一致、属于同一继承链的类型才能通过兼容性校验;哪怕两个类的公共结构完全相同,只要来自不同的独立继承体系,就无法实现互相赋值
- 这套规则下,子类可以正常与父类实现赋值兼容,因为二者的非公共成员来自同一份声明源
对规则设计的疑问
当前规则的校验范围存在明显的优先级错位:严格校验的对象是类外部代码无法直接调用的非公共成员,却不对最容易触发运行时错误的公共成员做继承层级的来源校验。
问题复现代码
class Sugar { do() { console.log('Let\'s make our life sweeter!') } } class Dynamite { do() { console.log('Let\'s destroy everything!') } } let s: Sugar = new Sugar() let d: Dynamite = new Dynamite() // TypeScript 放行的、不符合预期的赋值操作 s = d // 运行时将输出完全偏离 Sugar 类设计目标的结果 s.do()
具体质疑点
- 上述两个类不存在任何共同父类,仅公共方法
do()的结构签名完全一致 - TypeScript 编译阶段不会拦截
s = d的赋值操作,最终执行s.do()时会触发和Sugar类设计完全相悖的运行时行为,没有任何提前的编译错误提示 - 规则逻辑的矛盾:
- 对类外部代码无法直接调用、几乎不可能被外部代码误调用的私有、受保护方法,做严格的继承层级来源校验
- 对最容易因为结构相似、赋值匹配错误引发线上问题的公共成员,仅匹配结构签名就放行,完全不校验两个类是否属于同一继承体系
内容的提问来源于stack exchange,提问作者Serge I
相关产品推荐
相关产品推荐

