首先抛出一个概念
TypeScript 是结构类型系统,类型之间的对比只会比较它们最终的结构,而会忽略它们定义时的关系。
上面这句话值得咀嚼
下面举栗说明这件事 上代码
interface Animal {
name: string;
}
let animal: Animal = {
name: 'Tom',
run: () => { console.log('run') }
};
上面这段代码是有问题的 也是毋庸置疑的 再看下面这段
interface Animal {
name: string;
}
interface Cat {
name: string;
run(): void;
}
let tom: Cat = {
name: 'Tom',
run: () => { console.log('run') }
};
let animal: Animal = tom;
上面这段代码是没问题的 是不是让人很费劲 下面我试图用一个故事解释下这个现象
long long ago, 在JS王国里,有一个国王,他觉得世界上最美妙的声音就是鸭子的叫声,于是国王召集大臣,要组建一个1000只鸭子组成的合唱团。大臣们找遍了全国,终于找到999只鸭子,但是始终还差一只,最后大臣发现有一只非常特别的鸡,它的叫声跟鸭子一模一样,于是这只鸡就成为了合唱团的最后一员。
于是大家定义了鸭子类型,“如果它走起来像鸭子,而且叫起来像鸭子,那么它就是鸭子”。
然后再结合下面这句话
TypeScript 是结构类型系统,类型之间的对比只会比较它们最终的结构,而会忽略它们定义时的关系。
得到结论
第一段代码 大臣们找到的鹅啊啥的并没有鸭子的叫声 是进不去乐队的 所以系统报错了
第二段代码 大臣们找到的这只鸡(类型之间的对比)是有鸭子的叫声(只会比较它们最终的结构) 所以系统没报错
下面在用个栗子说明下为什么要这样做
interface Animal {
name: string;
}
interface Cat {
name: string;
run(): void;
}
let animal: Animal = {
name: 'Tom',
};
let tom: Cat = animal;
这段代码跟第二段代码对比 let tom: Cat = animal;
本身Cat类型的tom是具备run的能力的 但是被赋值成Animal类型的animal后就会失去run这个能力 必然会影响后续的使用 故ts提前抛出错误 而let animal: Animal = tom;
Animal类型的animal所具备的name Cat类型的tom也是具备的 所以就算被赋值也不会影响后续的使用
最后借用别人总结的话animal
断言为 Cat
,只需要满足 Animal
兼容 Cat
或 Cat
兼容 Animal
即可animal
赋值给 tom
,需要满足 Cat
兼容 Animal
才行
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。