ts的联合类型是真的好用,也是真的“好难用“
1、什么是联合类型
联合类型(Union Types)表示取值可以为多种类型中的一种。
例如:
type UT = string | number
type UT1 = {name: string} | {code: number}
2、使用联合类型
2.1 如何在使用的时候确认具体的类型
比如上面我们定义的 UT ,它既可能是 string, 也可能是 number。这个问题在js中又是如何处理的呢?
在js里面,有一些内置函数:
-
typeof: 区域不同基本类型和引用类型
-
instanceof:具体是否是类的实例
-
Array.isArray:是否是数组
type UT = string | number
const unkownValue = undefined as any as UT
if(typeof unkownValue === 'string') {
// 可以使用字符串的方法
}
if(typeof unkownValue === 'number') {
// 可以使用数字的方法
}
2.2 类型守卫(类型保护)
上面所使用的这些函数都是起到了类型保护的作用,但是这些方法并不能完全满足日常需求,比如不同类型的对象就无法作区分】
type UserA = { type: 'A', name: string }
type UserB = { type: 'B', name: string, code: number }
type Users = UserA | UserB
const user: Users = xxx
// 该如何判断user到底是userA还是userB呢?
-
使用类型谓词 is ,封装特定类型对象的判断函数
function isUserB(user: Users): user is UserB { return (user as UserB).code !== undefined } // 类似typeof的能力 if (isUserB(user)) { // 类型被确定为UserB了 } ``` -
使用唯一标识属性, 一般来说会配合枚举一起来用
if (user.type === "A") { // 类型被确定为UserA了 } if (user.type === "B") { // 类型被确定为UserB了 } ```
3、联合类型在体操中的表现
3.1 extends关键词
当联合类型作为范型的值在 extends 的前面使用时,每一项都进行判断(extends关键词在体操中是判断是否符合,而不是继承)
type UT = string | number
type IsString<T> = T extends string ? 1 : 2
// 答案是什么
type Res = IsString<UT>
查看答案
Res = 1 | 2// 这是因为UT的每一项都会进行判断// 大概全等于:
string extends string ? 1 : 2 | number extends string ? 1 : 2
当联合类型作为范型的值在 extends 的后面使用时,当成一个整体
type UT = string | number
type IsIncludeString<T> = string extends T ? 1 : 2
// 答案是什么
type Res = IsIncludeString<UT>
查看答案
Res = 1//大概全等于:string extends (string | number) ? 1 : 2
3.2 特别注意
前面强调了一个重点,即联合类型作为范型的值。如果是直接作为字面量,那么还是会当成一个整体
type UT = string | number
type IsString = UT extends string ? 1 : 2 // 答案是 2
3.3 在字符串模板中使用
在字符串模板则会产生类似笛卡尔积的效果
type Codes = 1 | 2 | 3
type Users = 'bob' | 'gave' | 'bar'
type All = `${Users}-${Codes}` // 答案是?
查看答案
type All = "bob-1" | "bob-2" | "bob-3" | "gave-1" | "gave-2" | "gave-3" | "bar-1" | "bar-2" | "bar-33.4 多个对象联合类型用 & 符号(交叉类型)时候,也会产生类似笛卡尔积的效果
type Codes = {a: 1} | {b: 3}
type Users = {name: 3} | {code: 1}
type Test = Codes & Users // 答案是?
其实到最后会发现,联合类型本身就是不确定类型,我们一直在想办法让他类型确定(即:类型保护)