複合型別 Union & Intersection
Union
type UnionSet1 = number | string;
type UserInfo1 = {
name: string,
age: number
};
type UserInfo2 = {
hasPet: boolean,
ownsMotorcycle: boolean,
};
// 按照數學推理理應只有三種組合:
// 1. 只有 UserInfo1:PASS
let maxwellOnlyInfo1: UnionSet2 = {
name: 'Maxwell',
age: 20
};
// 2. 只有 UserInfo2:PASS
let maxwellOnlyInfo2: UnionSet2 = {
hasPet: false,
ownsMotorcycle: true
};
// 3. 都有:PASS
let maxwellOnlyInfo3: UnionSet2 = {
name: 'Maxwell',
age: 20,
hasPet: false,
ownsMotorcycle: true
};
以上code與數學聯集觀念相似,But
// 理應要錯誤的組合:
type UserInfo1 = {
name: string,
age: number
};
type UserInfo2 = {
hasPet: boolean,
ownsMotorcycle: boolean,
};
type UnionSet2 = UserInfo1 | UserInfo2;
// 1. UserInfo1 和 UserInfo2 皆缺屬性:保證錯!
let maxwellWithPartialInfo1: UnionSet2 = {
name: 'Maxwell',
// age: 20, <-- 缺這個屬性
// hasPet: false, <-- 缺這個屬性
ownsMotorcycle: true
};
// 2. UserInfo1 滿足但 UserInfo2 有缺屬性:PASS
let maxwellWithPartialInfo2: UnionSet2 = {
name: 'Maxwell',
age: 20,
// hasPet: false, <-- 缺這個屬性
ownsMotorcycle: true
};
// 3. UserInfo2 滿足但 UserInfo1 有缺屬性:PASS
let maxwellWithPartialInfo3: UnionSet2 = {
// name: 'Maxwell', <-- 缺這個屬性
age: 20,
hasPet: false,
ownsMotorcycle: true
};
// 空集合一定錯
// let maxwellWithNoInfo: UnionSet2 = {};
理所當然,第一個案例一定錯,因為既不滿足 UserInfo1 也不滿足 UserInfo2;然而後續的例子,只要至少其中一個型別被判定滿足,不管其他型別有沒有完整補齊,TypeScript 認為無所謂。
其實這行為比較像OR
- 你可以選擇只要符合 UserInfo1 要求的型別或介面格式
- 或(OR)你可以選擇只要符合 UserInfo2 要求的型別或介面格式
- 但你也可以全部都符合
- 不過就是至少一個條件一定要滿足,否則出錯!因此空集合概念在這裡也不覆存在,會被認定是錯的,因為 OR 邏輯本來就是建立在其中一方符合的條件下才能滿足的。
Intersection
type UserInfo1 = {
name: string,
age: number
};
type UserInfo2 = {
hasPet: boolean,
ownsMotorcycle: boolean,
};3
type IntersectionSet = UserInfo1 & UserInfo2;
// 正確格式,所有屬性必須都出現
let correctInfo: IntersectionSet = {
name: 'Maxwell',
age: 20,
hasPet: false,
ownsMotorcycle: true
};
// 錯誤格式,屬性缺一不可
let wrongInfo1: IntersectionSet = {
// name: 'Maxwell', <-- 少一個 UserInfo1 屬性
age: 20,
hasPet: false,
ownsMotorcycle: true
};
let wrongInfo2: IntersectionSet = {
name: 'Maxwell',
age: 20,
hasPet: false,
// ownsMotorcycle: true <-- 少一個 UserInfo2 屬性
};
根據 UserInfo1 跟 UserInfo2 各自的型別格式,有沒有認真想過它們有何交集點?
name 與 age 以及 hasPet 與 ownsMotorcycle 的組合 —— 兩組屬性的集合中,完全沒有交集!偏偏在 TypeScript 裡 —— 交集 intersection 的用法是:將兩個可以為型別或介面的組合裡的格式進行結合的概念。
- 你必須符合 UserInfo1 和(AND)UserInfo2 的型別或介面格式
- 只要少了一個屬性就會出錯,完全符合 AND 邏輯的真諦
Never
/* 原始型別複合 */
type PrimitiveIntersection = number & string;
既是數字和字串的東西,當然不存在,但是隱身於所有型別當中的共通點。
never is a subtype of and assignable to every type.
任何型別 T(包含 never 本身)和 never 進行 union ,則型別 T 會吸收掉 never 型別:
type WontBeNever = T | never;
// => WontBeNever: T
任何型別 U(包含 never 本身)和 never 進行 intersection ,則型別 U 會被 never 型別強行覆蓋:
type MustBeNever = U & never;
// => MustBeNever: never