联合类型
分布式条件类型
当类型参数为联合类型,并且在条件类型左边直接引用该类型参数时,TypeScript 会把每一个元素单独传入进行类型运算,最后再合并成联合类型,这种语法叫分布式条件类型。
ts
type U = "a" | "b" | "c"
type Res = `${U}~~` // "a~~" | "b~~" | "c~~"type U = "a" | "b" | "c"
type Res = `${U}~~` // "a~~" | "b~~" | "c~~"IsUnion
判断联合类型
ts
type IsUnion<A, B = A> = A extends A ? ([B] extends [A] ? false : true) : never
type Res = IsUnion<"a" | "b">
type Res1 = IsUnion<["a" | "b"]>type IsUnion<A, B = A> = A extends A ? ([B] extends [A] ? false : true) : never
type Res = IsUnion<"a" | "b">
type Res1 = IsUnion<["a" | "b"]>A extends A触发分布式条件类型,让 A 的每个类型单独传入[B] extends [A]避免触发 B 的分布式条件类型,和单个类型的 A 比较
进一步理解
- 当 A 是联合类型时:
A extends A只是为了触发分布式条件类型,让每个类型单独传入A extends A和[A] extends [A]不同- 前者是单个类型和整个类型做判断
- 后者两边都是整个联合类型
- 只有 extends 左边直接是类型参数才会触发分布式条件类型
BEM
BEM 是 CSS 命名规范,用 block__element--modifier 的形式来描述某个区块下面的某个元素的某个状态的样式。
ts
type BEM<
Block extends string,
element extends string[],
modifier extends string[],
> = `${Block}__${element[number]}--${modifier[number]}}`
type Res = BEM<"B", ["e1", "e2"], ["m1", "m2"]>
// "B__e1--m1}" | "B__e1--m2}" | "B__e2--m1}" | "B__e2--m2}"type BEM<
Block extends string,
element extends string[],
modifier extends string[],
> = `${Block}__${element[number]}--${modifier[number]}}`
type Res = BEM<"B", ["e1", "e2"], ["m1", "m2"]>
// "B__e1--m1}" | "B__e1--m2}" | "B__e2--m1}" | "B__e2--m2}"AllCombinations
全组合
传入 "A" | "B" ,返回 "A" | "B" | "AB" | "BA"
ts
type Combination<A extends string, B extends string> =
| A
| B
| `${A}${B}`
| `${B}${A}`
type AllCombinations<A extends string, B extends string = A> = A extends A
? Combination<A, AllCombinations<Exclude<B, A>>>
: never
type Res = AllCombinations<"A" | "B"> // "A" | "B" | "AB" | "BA"type Combination<A extends string, B extends string> =
| A
| B
| `${A}${B}`
| `${B}${A}`
type AllCombinations<A extends string, B extends string = A> = A extends A
? Combination<A, AllCombinations<Exclude<B, A>>>
: never
type Res = AllCombinations<"A" | "B"> // "A" | "B" | "AB" | "BA"
Ayingotts's notes