- 引用:
 - 联合类型(Union Types)
 - 联合类型表示取值可以为多种类型中的一种。
 - 联合类型代表了一组类型的可用集合,只要最终赋值的类型属于联合类型的成员之一,就可以认为符合这个联合类型。
 - 联合类型使用 
|分隔每个类型 let a: string | number表示的含义是变量a的类型可以是string类型也可以是number类型
let a: string | number // Union Typesa = 1 // oka = '1' // ok
type Mixed = (...regs: any[]) => void | null// oklet fn1: Mixed = null// okconst fn2: Mixed = () => {console.log('hello')}
- 当 ts 不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型里共有的属性或方法
 - 联合类型的变量在被赋值的时候,会根据类型推论的规则推断出一个类型
 - 类型保护机制
- 如果一个变量的类型可能会多种情况,通过触发 ts 的类型保护机制来明确变量的具体类型
 - 在使用联合类型时,一个变量的类型有多种可能的情况,可结合类型保护机制来区分变量的具体类型
 - 比如 
typeof、instanceof…… 都可以触发 ts 的类型保护机制 
 
function getLength(x: string | number): number {return x.length; // error// 会报错:因为 string 有 length,number 没有 length}function getLength(x: string | number): number {return x.toString().length // ok// 不会报错,因为 toString 是 string 和 number 共有的成员}function getLength(x: string | number): number {// 使用 typeof 触发类型保护机制if (typeof x === 'string') {// 程序执行到这里,可以明确 x 的类型一定是 stringreturn x.length} else {// 程序执行到这里,可以明确 x 的类型一定是 numberreturn x.toString().length}}
let a: number | stringa // ts 无法明确 a 的类型,ts 认为 a 可能是 number 或 stringa = 1a // 程序执行到这里,ts 能明确 a 是 number 类型a = '1'a // 程序执行到这里,ts 能明确 a 是 string 类型
- 你可以在联合类型中进一步嵌套联合类型,但这些嵌套的联合类型最终都会被展平到第一级中
 
type Union1 = (string | number) | boolean;// 等效写法 👇type Union2 = string | number | boolean;type Union3 = ((string | number) | boolean) | (null | undefined);// 等效写法 👇type Union4 = string | number | boolean | null | undefined;
- 【应用】通过多个对象类型的联合,来实现手动的互斥属性,即这一属性如果有字段 1,那就没有字段 2
 
interface Tmp {user: {vip: trueexpires: string} | {vip: falsepromotion: string}}declare var tmp: Tmp;if (tmp.user.vip) {console.log(tmp.user.expires);// ts 能够推断出 tmp.user 的类型:// (property) Tmp.user: {// vip: true;// expires: string;// }} else if (tmp.user.vip === false) {console.log(tmp.user.promotion);// ts 能够推断出 tmp.user 的类型:// tmp.user// Tmp.user: {// vip: false;// promotion: string;// }}
注解
这是 ts 的类型收窄(type narrowing)或称为类型判别(type discrimination)的一个示例。ts 能够根据运行时检查来收窄或判别一个值的类型。在上述程序中,我们有一个 Tmp 接口,它描述了一个 user 属性,该属性可以有两种不同的形态。
- 当 
vip是true时,它有一个expires属性。 - 当 
vip是false时,它有一个promotion属性。 
当我们在程序中检查 tmp.user.vip 的值时,ts 能够收窄 tmp.user 的可能类型。
在 if (tmp.user.vip) 块中,ts 已经确定 vip 为 true,所以它可以确定 tmp.user 的类型为 { vip: true; expires: string; }。这就是为什么我们可以安全地访问 tmp.user.expires 而不会收到类型错误。
在 else if (tmp.user.vip === false) 块中,ts 知道 vip 为 false,所以它可以确定 tmp.user 的类型为 { vip: false; promotion: string; }。这就是为什么我们可以安全地访问 tmp.user.promotion 而不会收到类型错误。
这种基于运行时检查来收窄类型的能力是 ts 的一个强大特性,它允许开发者编写更安全、更容易理解的代码。
