第 5 卷
5} else { 6// 此处 value 被推断为 number
7console.log(value.toFixed(2));
8} 9}
- instanceof 类型守卫(检查类实例):
Code block
1class Dog { 2bark() { console.log("汪汪"); }
3} 4class Cat {
5meow() { console.log("喵喵"); } 6}
7
| 8 | function animalSound(animal: Dog | Cat) { |
|---|---|
| 9 | if (animal instanceof Dog) { |
| 10 | animal.bark();//推断为Dog |
| 11 | } else { |
| 12 | animal.meow();//推断为Cat |
| 13 | } |
| 14 | } |
- 自定义类型守卫(返回 is T 类型):
Code block
1interface User { 2name: string;
3age: number;
4} 5
6// 自定义类型守卫函数 7function isUser(obj: unknown): obj is User {
8return typeof obj === "object" && obj !== null && "name" in obj && "age"
in obj;
9}
- in 操作符类型守卫(检查对象属性):
Code block
1interface Admin { 2role: string;
3} 4interface User {
5name: string;
6} 7
| 8 | function printRole(obj: Admin | User) { |
|---|---|
| 9 | if ("role" in obj) { |
| 10 | //推断为Admin |
| 11 | console.log(obj.role); |
| 12 | } else { |
| 13 | //推断为User |
| 14 | console.log(obj.name); |
| 15 | } |
| 16 | } |
11. TypeScript 编译过程的逐步类型检查和擦除
逐步类型检查
TS 编译时会按代码执行流程逐步检查类型一致性,核心步骤:
- 词法/语法分析:检查代码语法是否合法,生成 AST;
- 绑定阶段:建立变量/类型的映射关系;
- 类型检查:
- 检查变量赋值、函数参数、返回值的类型是否匹配;
- 检查条件分支中的类型缩小(如类型守卫);
- 检查泛型、接口、枚举等自定义类型的一致性;
- 发现类型错误时抛出编译警告/错误。
- JS 运行时不支持 TS 类型系统;
- 避免类型代码增加运行时开销。
示例对比:
Code block
1// TS 代码(带类型)
| 2 | function add(a: number, b: number): number { |
|---|---|
| 3 | return a + b; |
| 4 | } |
5 6// 编译后 JS 代码(类型擦除)
7function add(a, b) { 8return a + b;
9}
注意:枚举、命名空间等特性编译后会生成少量 JS 代码(非类型代码),而接口、类型别名、泛型等纯类型代码会完全擦除。
12. TypeScript 与现有 JS 库的集成 & 声明文件 (.d.ts)
核心问题
JS 库(如 jQuery、Lodash)无 TS 类型标注,TS 无法识别其类型,导致使用时报错或失去类型提示。
解决方案:声明文件 (.d.ts)
声明文件是描述 JS 库类型的纯类型文件,后缀为 .d.ts,仅包含类型注解,无具体实现,核心作用:
- 为 JS 库提供类型信息,让 TS 识别其 API;
- 无需修改原 JS 库代码,实现“无侵入式类型支持”。
声明文件的使用方式
- 使用社区现成的声明文件(推荐):
大多数主流 JS 库的声明文件已收录在 @types 仓库,安装即可:
Code block
1# 安装 jQuery 的声明文件