ts中的 extends 和 infer
1. extends
extends 主要有两个作用:
1.1 条件判断 判断一个类型是否是另外一个类型字类型
type isNumber<T> = T extends number ? true : false
// 相当于 type falseTyp = false
type falseType = isNumber<'Rock'>
// 相当于 type trueType = true
type trueType = isNumber<3>
1.2 类型约束 约束某一个类型必须具有某些特征
interface containLength {
length: number;
}
function getLength<T extends containLength>(arr: T) {
return arr.length;
}
const obj = {
a: 1,
b: 2,
};
// 报错,信息如下图
getLength(obj);
//不报错,因为数组具有length属性。
getLength([1, 2, 3]);
信息的大概意思就是 obj 中没有length 属性
2. infer 类型推断
infer 其实比较比较简单。但是有时涉及协变和逆变就比较复杂(交叉类型和联合类型的转换)。我们可以从一个简单的例子入手
2.1 提取函数的参数的类型
type ParamType<T> = T extends (arg: infer P) => any ? P : T;
这个类型计算的意思是 : 如果T可以赋值给 (arg: infer P) => any, 就返回P , 否则返回T
type funcType = (arr: boolean) => { a: number; b: string };
//等价于 type test = boolean
type test = ParamType<funcType>;
funcType 可以赋值给 (arg: infer P) => any , 因此返回arg 的类型,而arg 的类型就是boolean
2.2 提取函数的返回值的类型
type ReturnType<T> = T extends (...agrgs:any[])=>infer P ? P : any
2.3 tuple 转 union
如:[string, number] -> string | number
// tuple 转 union ,如:[string, number] -> string | number
type tuple = [string,number]
type Tuple2Union<T> = T extends Array<infer P> ? P : never
// 相当于 type union = string | number
type union = Tuple2Union<tuple>
还有一种解决办法(比较简单不需要使用infer):
type Tuple2Union1<T extends Array<any>> = T[number]。
下一篇文章: 总结类型安全、协变和逆变、里氏替换原则、面向对象的多态。