基本原理
if(A <= B)
if(A <= B) true else false
type A = 1; type B = 1 | 2; type Result = A extends B ? true : false; // true
if(A <= B) and (C <= D)
type A = 1;
type B = 1 | 2;
type C = 3;
type D = 3 | 4;
type Result = A extends B
? C extends D
? 'true, true'
: 'true, false'
: C extends D
? 'false, true'
: 'false, false'; // "true, true"
空元组
type A = []; type IsEmptyArray<Arr extends unknown[]> = Arr['length'] extends 0 ? true : false; type Result = IsEmptyArray<A>; // true
元组与数组的区别是:数组长度没有限制,而元组长度有限制;
可以理解为:元组就是长度固定的数组
非空元组
type A = [1]; type NotEmpty<Arr extends unknown[]> = Arr extends [...infer X, infer Last] ? true : false; type Result = NotEmpty<A>; // true
[...infer X, infer Last] 表示至少存在一个元素的数组,那么 Arr extends [...infer X, infer Last] 表示的意思是:Arr 是否属于(包含于)一个非空数组
判断是否为非空元组的两种方法:
array['length'] !== 0array extends [...infer X, infer Rest] === true
递归
type A = ['Ich', '☆', 'liebe', '☆', 'dich']; type Reverse<Arr extends unknown[]> = Arr extends [...infer Rest, infer Last] ? [Last, ...Reverse<Rest>] : Arr; type Result = Reverse<A>; // ["dich", "☆", "liebe", "☆", "Ich"]
警告
注意:递归是有层数限制的
模式匹配 + infer 引用
type Tuple = ['Ich', '☆', 'liebe', '☆', 'dich']; type Result1 = Tuple extends [infer First, ...infer Rest] ? First : never; // "Ich" type Result2 = Tuple extends [infer First, ...infer Rest] ? Rest : never; // ["☆", "liebe", "☆", "dich"]
inter出现在条件类型中,通常与extends关键字一起使用infer显示地声明了一个新的泛型变量,用于表示待推断的类型- 当一个类型无法通过简单的方式访问到时, 我们可以使用
infer关键字来实现对其的快速访问;换言之,使用infer往往是因为后面需要用到对应的变量,比如上述的First和Rest,表示做一个引用(个人理解)
不写引用,直接写类型也是可以的
type Tuple = ['Ich', '☆', 'liebe', '☆', 'dich']; type Result1 = Tuple extends [infer First, ...string[]] ? First : never; // "Ich" type Result2 = Tuple extends ['Ich', ...infer Rest] ? Rest : never; // ["☆", "liebe", "☆", "dich"]
元组体操
[1] => [1, 2]
type A = [1]; type B = [...A, 2]; // [1, 2]
[1, 2] [3, 4] => [1, 2, 3, 4]
type B = [1, 2]; type C = [3, 4]; type D = [...B, ...C]; // [1, 2, 3, 4]
[1, 2, 3, 4] => 4
type D = [1, 2, 3, 4]; // 注意 1,2,3,4 都是类型,不是值 type Last<T> = T extends [...items: unknown[], last: infer X] ? X : never; type E = Last<D>; // ^--- E = 4 注意这里的 4 是类型,不是值
这里顺便提一下错误的写法
type D = [1, 2, 3, 4]; // 注意 1,2,3,4 都是类型,不是值 type Last<T extends unknown[]> = T[T["length"] - 1] // TS 并没有提供 - 1 操作 type E = Last<D>
[1, 2, 3, 4] => [1, 2, 3]
type D = [1, 2, 3, 4]; // 注意 1,2,3,4 都是类型,不是值 type NoLast<T> = T extends [...infer X, unknown] ? X : never; type E = NoLast<D>; // ^--- E = [1,2,3] 注意是类型,不是值
字符串体操
'a' => 'A'
type A = 'vivy'; type B = Capitalize<A>; // ^-- type B = "Vivy" type C = 'Ich' | '☆' | 'liebe' | '☆' | 'dich'; type X = Capitalize<C>; // ^-- type X = "Ich" | "☆" | "Liebe" | "Dich"
对联合类型使用 Capitalize 依旧遵循前面讲的分配率,即对每个类型单独进行大写操作后再合并起来
/** * 全变成大写 */ type Uppercase<S extends string> = intrinsic; /** * 全变成小写 */ type Lowercase<S extends string> = intrinsic; /** * 首字母大写 */ type Capitalize<S extends string> = intrinsic; /** *首字母小写 */ type Uncapitalize<S extends string> = intrinsic;
intrinsic 表示是 TS 内置的泛型
'a' 'b' => 'ab'
type A = 'Ich';
type B = '☆';
type C = 'liebe';
type D = '☆';
type E = 'dich';
type X = `${A} ${B} ${C} ${D} ${E}`;
// ^-- type X = "Ich ☆ liebe ☆ dich"
'ab' => 'a'
type A = "Ich ☆ liebe ☆ dich"
type First<T> = T extends `${infer F}${string}` ? F : never
type Result = First<A>
// ^-- "I"
'ab' => 'b'
字符串模式匹配的缺陷:只能获取到字符串中的第一个字符,获取不到最后一个字符
那么如何才能做到获取最后一个字符呢?
这里给出思路:
- 我们可以获取元组的最后一项
- 字符串可以转为元组
- 我们可以获取字符串的最后一项
type LastOfTuple<T extends unknown[]> = T extends [...infer _, infer Last]
? Last
: never;
type StringToTuple<S extends string> = S extends `${infer First}${infer Rest}`
? [First, ...StringToTuple<Rest>]
: [];
type LastOfString<T extends string> = LastOfTuple<StringToTuple<T>>;
type Result = LastOfString<'Ich ☆ liebe ☆ dich'>;
// ^-- "h"
string => 联合类型
type StringToUnion<S extends string> = S extends `${infer First}${infer Rest}`
? First | StringToUnion<Rest>
: never;
type Result = StringToUnion<'Ich☆liebe☆dich'>;
// type Result = "I" | "c" | "h" | "☆" | "l" | "i" | "e" | "b" | "d"
注意:联合类型自动去重了
string => 元组
type StringToTuple<S extends string> = S extends `${infer First}${infer Rest}`
? [First, ...StringToTuple<Rest>]
: [];
type Result = StringToTuple<'Ich☆liebe☆dich'>;
// type Result = ["I", "c", "h", "☆", "l", "i", "e", "b", "e", "☆", "d", "i", "c", "h"]
注意:元组没有去重
评论区
评论加载中...