Appearance
类型缩小
类型缩小:一个较为宽泛的集合缩小到相对较小、较明确的集合
类型守卫
通过类型守卫缩小子类型
js
{
let func = (anything: any) => {
if (typeof anything === 'string') {
return anything // 类型是 string
} else if (typeof anything === 'number') {
return anything // 类型是 number
}
return null
}
}等值判断或流程控制语句
通过字面量类型等值判断(===)或其他控制流语句(包括但不限于 if、三目运算符、switch 分支)将联合类型收敛为更具体的类型
tsx
{
type Goods = 'pen' | 'pencil' | 'ruler'
const getPenCost = (item: 'pen') => 2
const getPencilCost = (item: 'pencil') => 4
const getRulerCost = (item: 'ruler') => 6
const getCost = (item: Goods) => {
if (item === 'pen') {
return getPenCost(item) // item => 'pen'
} else if (item === 'pencil') {
return getPencilCost(item) // item => 'pencil'
} else {
return getRulerCost(item) // item => 'ruler'
}
}
}特殊值问题:通过 object 无法排除 null
tsx
const el = document.getElementById('foo') // Type is HTMLElement | null
if (typeof el === 'object') {
el // Type is HTMLElement | null
}空字符串和 0:无法通过 !x 排除 number,string,因为 0,'' 都是 falsy 值。
tsx
function foo(x?: number | string | null) {
if (!x) {
x // Type is string | number | null | undefined
}
}标签联合
放置一个明确标签,帮助 ts 确认类型
tsx
interface UploadEvent {
type: 'upload'
filename: string
contents: string
}
interface DownloadEvent {
type: 'download'
filename: string
}
type AppEvent = UploadEvent | DownloadEvent
function handleEvent(e: AppEvent) {
switch (e.type) {
case 'download':
e // Type is DownloadEvent
break
case 'upload':
e // Type is UploadEvent
break
}
}