类型守卫
TypeScript 类型守卫(Type Guards) 是一种在代码运行时执行检查,从而让编译器在某个范围内收窄变量类型的方式。它的核心目标是:通过条件语句让 TS 更准确地推断变量类型。
提示
类型守卫 只在条件分支内生效
typeof 守卫
用于 基本类型(string, number, boolean, symbol, bigint, undefined, function)。
ts
function printValue(value: string | number) {
if (typeof value === "string") {
console.log(value.toUpperCase()) // string 类型
} else {
console.log(value.toFixed(2)) // number 类型
}
}instanceof 守卫
用于 对象实例。
ts
class Dog {
bark() {}
}
class Cat {
meow() {}
}
function animalSound(animal: Dog | Cat) {
if (animal instanceof Dog) {
animal.bark()
} else {
animal.meow()
}
}in守卫
用于检查对象是否包含某个属性。
ts
type Fish = { swim: () => void }
type Bird = { fly: () => void }
function move(animal: Fish | Bird) {
if ("swim" in animal) {
animal.swim()
} else {
animal.fly()
}
}自定义类型守卫(is)
自定义类型守卫就是你写一个函数,这个函数的返回值类型使用 类型谓词(Type Predicate) 来告诉 TS “如果这个函数返回 true,那参数就是某种类型”。
- 返回值必须是布尔值(TS 不会去理解函数逻辑,只看你写的类型谓词)
- 类型守卫函数通常用 isXXX、hasXXX 命名,直观表示结果
- 和 typeof、instanceof 不同,自定义守卫适合 复杂对象、接口、联合类型
ts
const opt = Object.prototype.toString
export function isArray(obj: any): obj is any[] {
return opt.call(obj) === '[object Array]'
}
export function isObject(obj: any): obj is { [key: string]: any } {
return opt.call(obj) === '[object Object]'
}
export function isString(obj: any): obj is string {
return opt.call(obj) === '[object String]'
}
export function isNumber(obj: any): obj is number {
return opt.call(obj) === '[object Number]' && obj === obj
}ts
//如果Object中存在数字,就保留两位数字,如果是字符串,则去除空格,如果是函数,则执行
function handleObject(arg: any) {
if (isObject(arg)) {
let val // 循环外声明变量可以节省空间
Object.keys(arg).forEach((key) => {
// for...in会遍历到原型
val = arg[key]
if (isNumber(val)) {
arg[key] = val.toFixed(2)
}
if (isString(val)) {
arg[key] = val.trim()
}
if (isFunction(val)) {
val()
}
})
}
}判空守卫(可选链 + null 检查)
ts
function printLength(str?: string | null) {
if (str != null) {
console.log(str.length) // TS 知道 str 是 string
}
}文字类型守卫(字面量缩小)
ts
type Direction = "up" | "down" | "left" | "right"
function move(dir: Direction) {
if (dir === "up") {
console.log("向上")
} else if (dir === "down") {
console.log("向下")
}
}