原文:Mastering infer in TypeScript
infer 关键词使用
从现有的类型或者表达式中提取一个类型。当你需要从一个很大的类型中提取特定类型是非常有用。
type ExtractX<T> = T extends { x: infer U } ? U : never;
type Result1 = ExtractX<{x: string}>; // Result1 is string
type Result2 = ExtractX<{j: string}>; // Result2 is never
这里定义了一个通用类型 ExtractX,检查泛型参数 T 中是否有 x 属性,如果有,通过 infer 提取 x 属性的类型并分配给 U,否则返回 never。
函数类型提取
infer 可以从函数参数或返回类型中提取类型:
考虑这样一个场景,定义一个函数,如果参数是数组则返回第一个值,否则返回原值:
function firstItem(arg: any) {
return Array.isArray(arg) ? arg[0] : arg
}
var result = firstItem(['one', 'two']); // result is of type any
优化下 firstItem 函数的类型定义,确保在处理数组数据是可以返回数组元素的类型:
- 使用泛型 T 指定参数类型
- T 是数组时使用 infer 提取元素类型
function firstItem<T>(arg: T): T extends Array<infer U> ? U : T {
return Array.isArray(arg) ? arg[0] : arg;
}
var result1 = firstItem(['one', 'two']); // result1 is of type string
var result2 = firstItem([1, 2]); // result2 is of type number
var result3 = firstItem([1, 'two']); // result3 is of type string| number
var result4 = firstItem([]); // result4 is of type never
通过测试结果可以看到,函数返回来参数为数组格式时元素的类型
Mapped Types 推导
type MyMappedType<T> = {
[P in keyof T]: T[P] extends Array<infer U> ? U : T[P];
};
type Result1 = MyMappedType<{x: string[]}>; // Result1 is {x: string}
type Result2 = MyMappedType<{x: number[][]}>; // Result2 is {x: number[]}
infer 代码的收益
- 更安全的类型:推导类型是从较大类型中提取,不会出错
- 代码更有效:不用重新构造类型,在建立关系的同时类型不会出错,修改也会自上而下自动调整
- 更好的代码组织:通过将类型提取到各自的命名类型中,使得代码更有组织,容易阅读
原文:Mastering infer in TypeScript
infer 关键词使用
从现有的
类型或者表达式中提取一个类型。当你需要从一个很大的类型中提取特定类型是非常有用。这里定义了一个通用类型
ExtractX,检查泛型参数 T 中是否有x属性,如果有,通过infer提取x属性的类型并分配给U,否则返回never。函数类型提取
infer可以从函数参数或返回类型中提取类型:考虑这样一个场景,定义一个函数,如果参数是数组则返回第一个值,否则返回原值:
优化下
firstItem函数的类型定义,确保在处理数组数据是可以返回数组元素的类型:通过测试结果可以看到,函数返回来参数为数组格式时元素的类型
Mapped Types 推导
infer 代码的收益