释义
官网解释:
Within the extends clause of a conditional type, it is now possible to have infer declarations that introduce a type variable to be inferred. Such inferred type variables may be referenced in the true branch of the conditional type. It is possible to have multiple infer locations for the same type variable.
先解释conditional type
,也就是条件类型,形如T extends U ? X : Y
,有关键字extends,是TypeScript的高级类型之一,不懂的可以移步ts官网查询。
ok,懂了这个,就很容易翻译了:
在条件类型的子句中(即extends后的条件分支),可能需要推断声明一个需要声明的类型变量。这个需要声明的类型变量可能取决于条件类型正确的那一条分支,相同的类型变量可能会有多个推断路径(即多个连续的条件分支)
也就是说,infer
和extends
配合,用作类型推断的。而且infer
一般和extends后的子句有联系,如果没有,那就没必要使用了
话很难让人懂,直接看下面的例子
例子
type Case1<T> = T extends (infer U)[] ? U : string; //这里的意思是说:T 是否继承自类型 U[] ,这里开始推断 U ,以是的话右边等于 U,不是就等于 string
type Type1=Case1<number>; //不符合推断,进入Case1<T>错误分支,最终类型为string
type Type11=Case1<number[]>; //符合推断,今日Case1<T>正确分支,最终类型为number
extends可以递归使用。
测试题
描述
interface Logger {
time: number;
asyncLog:(msg: string) => Promise<string>;
syncLog:(msg: string) => number;
}
type Translate<T> = /** 你需要实现的部分 **/;
// 要求 Translate
// 1. 提取出为函数类型的属性,丢弃掉其它类型的属性
// 2. 将函数返回类型调整为形参类型(假定有且只有一个参数)
解决思想
- 通过
keyof
得到函数类型的属性的联合类型,丢弃其他类型的属性 - 通过infer转换原来的函数
解决
过滤不为函数的属性,该类型操控Logger得到的是联合类型"asyncLog"|"syncLog"
type FilterKeys<T> = {
[key in keyof T]: T[key] extends Function ? key : never;
}[keyof T]; // 小技巧,keyof 关键字不会提取类型为 never 的
使用inter关键字,通过已知类型转换需要的类型
type TranselteFunction<T> = T extends (p: infer U) => any ? (p: U) => U : never;
最后组合一起,遍历符合条件的属性名(联合类型),并转换成符合题意的类型。
type Translate<T> = {
[key in FilterKeys<T>]: TranselteReturntype<T[key]>
};