TypeScript(九)

87 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 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 中它并不关心,CatAnimal 在定义时是什么关系,只是看最终它们之间的结构是有什么关系。也就是说,等价于我们常说的 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);
}