TypeScript 2.7.2中为何不同类型参数调用函数在Angular6中无报错?
为什么将B类实例传给要求A类型的函数时没有报错?
在使用TypeScript 2.7.2的Angular 6项目中,我遇到了这样的情况:调用参数类型为A的func2函数时传入了B类实例,但既没有IDE错误,也没有--aot编译错误。相关代码如下:
函数调用代码
private func1() { const b: B = new B(); b.name = 'jack'; this.func2(b); } private func2(a: A) { console.log(a.name); // 输出 jack }
类定义
export class A { public name: string; } export class B { public name: string; public surname: string; }
这是因为TypeScript采用的是结构类型系统(Structural Typing),而不是Java、C#这类语言常用的名义类型系统(Nominal Typing),具体原因可以拆解为两点:
- TypeScript判断类型兼容性的核心依据是结构匹配,而非类名:只要一个类型拥有目标类型要求的所有属性和方法(结构是目标类型的超集),就允许互相赋值。这里
B类不仅包含了A类的所有属性(name: string),还多了surname属性,完全满足func2对参数类型A的要求,所以TS认为这个赋值是合法的。 - IDE的实时类型检查和Angular的
--aot编译都是基于TypeScript的类型规则实现的,自然会遵循这种结构兼容的逻辑,因此不会抛出错误。
如果想要强制实现名义类型(让A和B即使结构重叠也不能互相赋值),可以给每个类添加一个唯一的私有标识属性来区分:
export class A { public name: string; private readonly _type: 'A' = 'A'; // 唯一私有标识 } export class B { public name: string; public surname: string; private readonly _type: 'B' = 'B'; // 唯一私有标识 }
此时两个类的私有属性_type类型不同,结构不再兼容,再把B实例传给func2就会触发TypeScript的类型错误了。
内容的提问来源于stack exchange,提问作者chnselim
相关产品推荐
相关产品推荐

