TypeScript 如何做类型收窄
你或许听过不少 JavaScript 的坑:比如把数字和字符串混在一起运算,本该是对象的属性却不小心写成了 undefined,最后报的错连自己都懵。TypeScript 能帮我们提前揪出这类问题,而“类型收窄”就是它藏在背后的核心工具。
什么是类型收窄?
简单说,类型收窄就是 TypeScript 帮你把“宽泛的类型范围”缩小到“更具体的类型”的过程。比如你有一个变量可能是字符串,也可能是数字,它一开始的类型是 string | number;当你判断它是字符串后,TypeScript 就会自动把这个变量的类型收窄成 string,后续就能安全地用字符串的方法了。

举个生活化的例子:你手里有个“包装好的礼物”,不知道里面是苹果还是橙子,这就像 TypeScript 里的联合类型(比如 apple | orange)。当你拆开包装确认是苹果后,这个礼物就从“水果类”收窄成了“苹果”,你自然知道怎么洗、怎么切——这就是类型收窄的作用:让你在代码里能精准判断类型,避免“用苹果的方法切橙子”这类错误。
最常用的类型收窄方法:条件判断
最常见的收窄方式,就是用 JavaScript 里的 if 条件判断,TypeScript 会自动识别判断条件里的逻辑,把变量类型收窄。比如你写一段处理用户输入的代码:
`typescript
function printInput(input: string | number) {
if (typeof input === "string") {
// 这里input的类型被收窄成了string
console.log(input.toUpperCase());
} else {
// 这里input的类型被收窄成了number
console.log(input.toFixed(2));
}
}
`
如果没有类型收窄,你直接在 printInput 里调用 input.toUpperCase(),TypeScript 会报错——因为它不知道输入是字符串还是数字。但加了 typeof 判断后,代码就安全了:if 里只能用字符串的方法,else 里只能用数字的方法。
除了 typeof,instanceof 也很常用。比如你有一个日期对象和普通对象的联合类型,用 instanceof Date 就能把它收窄成 Date 类型:
`typescript
function getDateStr(date: Date | string) {
if (date instanceof Date) {
return date.toLocaleDateString();
} else {
return new Date(date).toLocaleDateString();
}
}
`
处理复杂类型:更灵活的收窄技巧
如果遇到对象或自定义类型,还可以用“属性判断”来收窄类型。比如你定义了两种不同的用户类型:管理员有 admin 属性,普通用户有 username 属性:
`typescript
type Admin = { admin: boolean; name: string };
type User = { username: string; age: number };
function greet(user: Admin | User) {
if ("admin" in user) {
// 这里user被收窄成Admin,能访问admin属性
return Hello, Admin ${user.name};
} else {
// 这里user被收窄成User,能访问username属性
return Hello, ${user.username};
}
}
`
这种“判断对象有没有某个属性”的方法,就像你通过“有没有遥控器”来判断面前的东西是电视还是空调——通过一个明确的特征,缩小范围。
还有一种更简单的情况:当你用 === 或 !== 做等于判断时,TypeScript 也会自动收窄类型。比如判断一个变量是不是 null:
`typescript
function processValue(value: string | null) {
if (value !== null) {
// 这里value被收窄成string
console.log(value.length);
}
}
`
如果没有这个判断,你直接访问 value.length,TypeScript 会提示你“value 可能是 null,不能访问属性”,而加了判断后,这个错误就消失了。
类型收窄的好处
很多人会觉得“类型收窄只是 TypeScript 的花架子”,但其实它能帮你少写很多“防御性代码”。比如不用每次都判断“是不是字符串”,TypeScript 已经帮你做了这件事;而且它能在开发阶段就把“类型错误”揪出来,避免上线后出现“undefined 不是函数”这类莫名其妙的 bug。
简单说,类型收窄就是 TypeScript 给开发者的“智能助手”——它帮你理清变量的类型边界,让你写代码的时候更安心,不用再反复回忆“这个变量到底是啥类型”。