二、 ts中的 extends 和 infer

167 阅读1分钟

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]);

image.png

信息的大概意思就是 obj 中没有length 属性

2. infer 类型推断

infer 其实比较比较简单。但是有时涉及协变和逆变就比较复杂(交叉类型和联合类型的转换)。我们可以从一个简单的例子入手

image.png

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]

下一篇文章: 总结类型安全、协变和逆变、里氏替换原则、面向对象的多态。