TypeScript细碎知识点:infer 常规用法
一、使用介绍
条件类型基本语法:
T extends U ? X : Y;
如果占位符类型U是一个可以被分解成几个部分的类型,譬如数组类型,元组类型,函数类型,字符串字面量类型等。这时候可以通过infer来获取U类型中某个部分的类型。
官方解释:现在在有条件类型的 extends 子语句中,允许出现 infer 声明,它会引入一个待推断的类型变量。 这个推断的类型变量可以在有条件类型的 true 分支中被引用。 允许出现多个同类型变量的 infer。
通俗的说:在有条件类型的 extends 子语句中,想要获取哪块的变量类型就在哪里用infer标注这个类型,
!!!重点要记住:
- 只能出现在有条件类型
extends的子语句中 - 引入infer会出现一个待推断的变量
- 推断的变量只能在
truef分支中被引用 。
二、常规用法
1. 数组(或者元组)
🐹 推断数组(或者元组)的类型
定义:
type InferArray<T> = T extends (infer U)[] ? U : never;
(infer U) 和 平时常写的 string[],number[] 等等是不是很像?这里就是通过(infer U)来获取数组对应的类型。
示例:
//定义类型工具 type InferArray<T> = T extends (infer U)[] ? U : never; //示例 type result0 = InferArray<[number, string]>; // string | number type result1 = InferArray<string[]>; // string type result2 = InferArray<number[]>; // number
🐹 推断数组(或者元组)第一个元素的类型
定义:
type InferFirst<T extends unknown[]> = T extends [infer P, ...infer _] ? P : never
[infer P, ... infer _]中infer P获取的是第一个元素的类型,而...infer _获取的是数组其他剩余元素的数组类型;
!!!特别说明下,我们例子汇总不需要使用其他元素的类型,所以用_。
示例:
//定义 type InferFirst<T extends unknown[]> = T extends [infer P, ...infer _] ? P : never //示例 type result = InferFirst<[3, 2, 1]>; // 3
🐹 推断数组(或者元组)最后一个元素的类型
定义:
type InferLast<T extends unknown[]> = T extends [...infer _, infer Last] ? Last : never;
这个 和 推断数组第一个元素的类型 类似,...infer _获取的是最后一个元素之前的所有元素类型,infer Last获取的是最后一个元素的类型。
示例:
//定义 type InferLast<T extends unknown[]> = T extends [...infer _, infer Last] ? Last : never; //示例 type result = InferLast<[3, 2, 1]> // 1
2. 函数
🐹 推断函数类型的参数
定义:
type InferParameters<T extends Function> = T extends (...args: infer R) => any ? R : never;
...args 代表的是函数参数组成的元组, infer R代表的就是推断出来的这个函数参数组成的元组的类型。
TS 已内置,名字叫Parameters<T>
示例:
//定义 type InferParameters<T extends Function> = T extends (...args: infer R) => any ? R : never; //示例 type result = InferParameters<((arg1: string, arg2: number) => void)>; // [string, number]
🐹 推断函数类型的返回值
定义:
type InferReturnType<T extends Function> = T extends (...args: any) => infer R ? R : never;
和前面的推断函数类型的参数类似,=> 后面的infer R代表的就是推断出来的函数的返回值类型。
TS 已内置,名字叫ReturnType<T>。
示例:
//定义 type InferReturnType<T extends Function> = T extends (...args: any) => infer R ? R : never; //示例 type result = InferReturnType<() => string>; // string
🐹 推断函数类型的构造函数参数类型
定义:
type InferConstructor<T> = T extends new (...args: infer P) => any ? P : never
我们想获取构造函数的参数类型,是不是只要把infer P标注在构造函数参数的位置就可。这个可以参考推断函数参数去理解
TS 已内置,名字叫ConstructorParameters<T>。
示例:
//定义 type InferConstructor<T> = T extends new (...args: infer P) => any ? P : never //示例 class People { name: string; constructor(name: string) { this.name = name } } //定义类型 type result = InferConstructor<typeof People> // string
🐹 4. 推断函数类型的实例类型(InstanceType)
定义:
type InferInstanceType<T> = T extends new (...args: any) => infer P ? P : never;
我们想获取构造函数People的实例类型,这个可以参考函数推断返回值去理解。
TS 已内置,名字叫InstanceType<T>。
示例:
//定义类型 type InferInstanceType<T> = T extends new (...args: any) => infer P ? P : never; //示例 class People { name: string; constructor(name: string) { this.name = name } } type result = InferInstanceType<typeof People> //People
🐹 5. 获取this参数的类型(ThisParameterType)
定义:
type InferFuncThisType<T> = T extends (this: infer P, ...args: any) => any ? P : T;
TS 已内置,名字叫ThisParameterType<T>。
示例:
// 定义 type InferFuncThisType<T> = T extends (this: infer P, ...args: any) => any ? P : T; //示例 function fn1(this: { name: string; age: number }) { this.name = "Type-Infer"; this.age = 13; } type result = InferFuncThisType<typeof fn1>;
3. Promise
🐹 推断Promise成功值的类型
定义:
type InferPromise<T> = T extends Promise<infer U> ? U : never;
示例:
//定义 type InferPromise<T> = T extends Promise<infer U> ? U : never; //示例 type result = InferPromise<Promise<string>>; // string
4. 模板类型
🐹 推断字符串字面量类型的第一个字符对应的字面量类型
定义:
type InferString<T extends string> = T extends `${infer First}${infer _}` ? First : [];
示例:
//定义 type InferString<T extends string> = T extends `${infer First}${infer _}` ? First : []; //示例 type result = InferString<"Johnny">; // J
🐹 去除字符串前面的所有空格
定义:
type TrimFront<T extends string> = T extends `${' '}${infer K}` ? TrimFront<K> : T
示例:
//定义 type TrimFront<T extends string> = T extends `${' '}${infer K}` ? TrimFront<K> : T //示例 type result = TrimFront<' Hello'> //Hello
🐹 去除字符串后面的所有空格
定义:
type TrimTail<T> = T extends `${infer Res}${' '}` ? TrimTail<Res> : T
示例:
//定义 type TrimTail<T> = T extends `${infer Res}${' '}` ? TrimTail<Res> : T //示例 type result = TrimTail<'Hello World '> //"Hello World"
🐹 实现字符串中某些字符替换(replace)方法
定义:
type InferReplace<T extends string, K extends string, U extends string> = T extends `${infer Left}${K}${infer Right}` ? `${Left}${U}${Right}` : T
示例:
//定义 type InferReplace<T extends string, K extends string, U extends string> = T extends `${infer Left}${K}${infer Right}` ? `${Left}${U}${Right}` : T //示例 type result = InferReplace<'hello world', 'wo', 'ha'> //'hello harld'
🐹 将字符串的第一个字符转成大些,如果不是字符串,则直接返回。
定义:
type CapitalizeString<T> = T extends `${infer P}${infer V}` ? `${Uppercase<P>}${V}` : T
Uppercase 是 lib.es5.d.ts 的内置方法。
示例:
//定义 type CapitalizeString<T> = T extends `${infer P}${infer V}` ? `${Uppercase<P>}${V}` : T //示例 type result1 = CapitalizeString<'handler'> // Handler type result2 = CapitalizeString<'parent'> // Parent type result3 = CapitalizeString<123> // 123
🐹 获取字符串字面量中的第一个字符
定义:
type FirstChar<T> = T extends `${infer P}${infer _}` ? P : never
示例:
//定义 type FirstChar<T> = T extends `${infer P}${infer _}` ? P : never //示例 type result1 = FirstChar<'ABC'> //A type result2 = FirstChar<'abc'> //a type result3 = FirstChar<''> //never
🐹 获取字符串字面量中的最后一个字符
定义:
type LastChar<T,Pre = never> = T extends `${infer P}${infer V}` ? LastChar<V,P> : Pre
关键点:1. 使用infer关键字配合模版字符串类型推导。 2. prev 临时变量,存储上次首字母。3. extends 递归寻找。
示例:
//定义 type LastChar<T,Pre = never> = T extends `${infer P}${infer V}` ? LastChar<V,P> : Pre //示例 type result1 = LastChar<'ABC'> //C type result2 = LastChar<'abc'> //c type result3 = LastChar<''> //never
🐹 将字符串转成元祖
定义:
type StringToTuple<T extends string> = T extends `${infer L}${infer R}` ? [L, ...StringToTuple<R>] : [];
关键点:1. 使用infer关键字配合模版字符串类型推导。 2. 三点运算符(...)展开数组. 3. extends 递归.
示例:
//定义 type StringToTuple<T extends string> = T extends `${infer L}${infer R}` ? [L, ...StringToTuple<R>] : []; //示例 type result1 = StringToTuple<'ABC'> // ['A','B','C'] type result2 = StringToTuple<'abc'> // ['a','b','c] type result3 = StringToTuple<''> // []
🐹 将元组转换成字符串
定义:
type TupleToString<T extends any[], Pre extends string = ''> = T extends [infer P, ...infer C] ? (P extends string ? TupleToString<C, `${Pre}${P}`> : never) : Pre
关键点:1. 使用infer配合元组类型推导。 2. extends 递归思想。 3. 使用泛型,增加一个变量使用。
示例:
//定义 type TupleToString<T extends any[], Pre extends string = ''> = T extends [infer P, ...infer C] ? P extends string ? TupleToString<C, `${Pre}${P}`> : never : Pre //示例 type result1 = TupleToString<['A', 'B', 'C']> // ['A','B','C'] type result2 = TupleToString<['a', 'b', 'c']> // ['a','b','c] type result3 = TupleToString<[]> // []
🐹 将一个泛型复制多分,变成字符串返回
定义:
type RepeatString< T extends string, // 字符串 C extends number, // 遍历个数 S extends string = "", // 临时结果 A extends any[] = [] // 结束条件 > = A["length"] extends C ? S : RepeatString<T, C, `${T}${S}`, [1, ...A]>;
关键点:1. 使用infer关键字。2. 增加多个变量. 3. 用泛型A约束结束条件,S,存储临时结果。
示例:
//定义 type RepeatString< T extends string, // 字符串 C extends number, // 遍历个数 S extends string = "", // 临时结果 A extends any[] = [] // 结束条件 > = A["length"] extends C ? S : RepeatString<T, C, `${T}${S}`, [1, ...A]>; //示例 type result1 = RepeatString<"a", 3> // "aaa" type result2 = RepeatString<"a", 0> // ""
🐹 将字符串字面量类型按照指定字符,分割为元组。无法分割则返回原字符串字面量
定义:
type SplitString< T extends string, // 初始字符串 C extends string, // 分隔符 B extends string = "", //临时结果 A extends any[] = [] // 最终结果 SplitString<T,C,S,B,A> > = T extends `${infer L}${infer R}` ? (L extends C ? SplitString<R, C, ``, [...A, B]> : SplitString<R, C, `${B}${L}`, A>) : [...A, B];
关键点:1. 使用infer关键字。2. 增加多个变量。3. 用泛型A存储最终结果,B存储临时结果。
示例:
//定义 type SplitString< T extends string, // 初始字符串 C extends string, // 分隔符 B extends string = "", //临时结果 A extends any[] = [] // 最终结果 SplitString<T,C,S,B,A> > = T extends `${infer L}${infer R}` ? (L extends C ? SplitString<R, C, ``, [...A, B]> : SplitString<R, C, `${B}${L}`, A>) : [...A, B]; //示例 type result1 = SplitString<"handle-open-flag", "-">; // ["handle", "open", "flag"] type result2 = SplitString<"open-flag", "-">; // ["open", "flag"] type result3 = SplitString<"handle.open.flag", ".">; // ["handle", "open", "flag"] type result4 = SplitString<"open.flag", ".">; // ["open", "flag"] type result5 = SplitString<"open.flag", ".">; // ["open.flag"]
🐹 计算字符串字面量类型的长度
定义:
type LengthOfString<T, RE extends any[] = []> = T extends `${infer L}${infer R}` ? LengthOfString<R, [L, ...RE]> : RE["length"];
关键点:1. 使用infer关键字。2. 用泛型RE存储最终结果,使用length获取长度返回。
示例:
//定义 type LengthOfString<T, RE extends any[] = []> = T extends `${infer L}${infer R}` ? LengthOfString<R, [L, ...RE]> : RE["length"]; //示例 type result1 = LengthOfString<"BFE.dev">; // 7 type result2 = LengthOfString<"">; // 0
浙公网安备 33010602011771号