携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第12天,点击查看活动详情
😊 大家好,我是思淼MJ。
上面文章总结了一部分 TypeScript 的“类型推断”,今天继续学习 TypeScript 的内容。
类型断言
类型断言的限制
先来回顾下上篇文章的内容,从之前的示例中,能够总结出:
- 联合类型可以被断言为其中一个类型
- 父类可以被断言成子类
- 任何类型都可以被断言为 any 类型
- any 可以被断言为任何类型
🤔问题:那么类型断言有没有什么限制呢?任何类型都可以被断言为任何另外一种类型吗?
📖答案:有限制;并不是任何一种类型都可以被断言为任何另外一种类型。
举个具体的例子🌰:
interface Animal {
name: string;
}
interface Cat {
name: string;
run(): void;
}
let tom: Cat = {
name: 'Tom',
run: () => { console.log('run') }
};
let animal: Animal = tom;
TypeScript 是结构类型系统,类型之间的的对比只会比较它们最终的结构,而会忽略它们定义时的关系。
从上面的例子中,我们可以看出,Cat 中 包含了 Animal 中的所有属性,除此之外,还新增了一个方法 run。
其实在 TypeScript 中它并不关心,Cat 与 Animal 在定义时是什么关系,只是看最终它们之间的结构是有什么关系。也就是说,等价于我们常说的 Cat extends Animal。
所以,上面的例子中 Cat 与 Animal 的关系等价于:
interface Animal {
name: string;
}
interface Cat extends Animal {
run(): void;
}
再回过头来看看,上面的例子,就会发现,也就不难理解,为什么 Cat 类型的 tom 可以赋值给 Animal 类型的 animal 了。就像是面向对象编程中一样,我们可以将子类的实例赋值给类型为父类的变量。
换成 TypeScript 中的说法来说,就是:Cat 兼容 Animal。
而当 Cat 兼容 Animal 的时候,我们就可以互相进行类型的断言了。
interface Animal {
name: string;
}
interface Cat {
name: string;
run(): void;
}
function testAnimal(animal: Animal) {
return (animal as Cat);
}
function testCat(cat: Cat) {
return (cat as Animal);
}