常见的类型保护有如下几种:
- typeof
- 平等缩小(例如:===、!==)
- instanceof
- in
# 一、类型缩小
# 1、typeof 守卫
function padLeft(padding: number | string, input: string) {
// typeof类型守卫👀
if (typeof padding === 'number') {
return ' '.repeat(padding) + input
}
return padding + input
}
# 2、范围缩小
- 真值/等值缩小
// 真值缩小
function printAll(strs: string | string[] | null) {
// 因为 typeof null 的结果为 'object'
if (strs && typeof strs === 'object') {
for (const s of strs) {
console.log(s)
}
} else if (typeof strs === 'string') {
console.log(strs)
}
}
// 等值缩小 👀
function printAll(strs: string | string[] | null) {
if (strs !== null) {
if (typeof strs === 'object') {
for (const s of strs) {
console.log(s)
}
} else if (typeof strs === 'string') {
console.log(strs)
}
}
}
printAll(['a', 'b', 'c'])
- in 和 instanceof
// 1、in
// 定义
type Fish = { swim: () => void }
type Bird = { fly: () => void }
function move(animal: Fish | Bird) {
if ('swim' in animal) {
return animal.swim()
}
return animal.fly()
}
// 使用
const fish: Fish = {
swim: function () {
console.log('鱼儿会游泳')
}
}
move(fish) // 传入回调函数
// 2、instanceof
function logValue(date: string | Date) {
if (date instanceof Date) {
console.log(date.getTime())
} else {
console.log(date.split(' '))
}
}
logValue(Date()) // 字符串类型
logValue(new Date()) // Date类型
# 3、类型谓词 😢
- 简单演示
// 缩小pet的范围
function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== undefined
}
详细示例
type Fish = {
name: string
swim: () => void
}
type Bird = {
name: string
fly: () => void
}
// 获取pet
function getSmallPet(): Fish | Bird {
let fish: Fish = {
name: 'shrkey',
swim: () => {}
}
let bird: Bird = {
name: 'sparrow',
fly: () => {}
}
return true ? bird : fish // 假设经过逻辑判断后得到的是bird
}
// 判断pet是什么
function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== undefined // ture的话,pet的类型就是Fish
}
let pet = getSmallPet() // pet是bird
if (isFish(pet)) {
pet.swim()
} else {
pet.fly()
}
const zoo: (Fish | Bird)[] = [getSmallPet(), getSmallPet(), getSmallPet()]
const underWater1: Fish[] = zoo.filter(isFish)
const underWater2: Fish[] = zoo.filter(isFish) as Fish[]
const underWater3: Fish[] = zoo.filter((pet): pet is Fish => {
if (pet.name === 'sharkey') return false
return isFish(pet)
})
# 二、更多内容
# 1、受歧视的 Union
前面我们解决的大都是简单的类型,那遇到联合类型(union)怎么办呢?
例如:下面的 cricle 和 square 联合类型
① 问题
interface Shape {
kind: 'circle' | 'square'
radius?: number
sideLength?: number
}
function getArea(shape: Shape) {
return Math.PI * shape.radius ** 2 // 报错:Object is possibly 'undefined'.
}
② 解决
- 非空断言 !
interface Shape {
kind: 'circle' | 'square'
radius?: number
sideLength?: number
}
function getArea(shape: Shape) {
return Math.PI * shape.radius! ** 2
}
- 分类 switch
interface Circle {
kind: 'circle'
radius: number
}
interface Square {
kind: 'square'
sideLength: number
}
type Shape = Circle | Square
function getArea(shape: Shape) {
switch (shape.kind) {
case 'circle':
return Math.PI * shape.radius ** 2
case 'square':
return shape.sideLength ** 2
}
}
# 2、never 类型
never 类型可以用于穷尽性检查。
以上面的代码为例:
interface Circle {
kind: 'circle'
radius: number
}
interface Square {
kind: 'square'
sideLength: number
}
interface Triangle {
kind: 'triangle'
sideLength: number
}
type Shape = Circle | Square | Triangle
function getArea(shape: Shape) {
switch (shape.kind) {
case 'circle':
return Math.PI * shape.radius ** 2
case 'square':
return shape.sideLength ** 2
default:
const _exhaustiveCheck: never = shape // 报错:Type 'Triangle' is not assignable to type 'never'.
return _exhaustiveCheck
}
}