ps:如果对TS的一些进阶使用不太熟悉可以先去看看
场景一
使用场景如下所示:我们需要从AuthStore 中推导出UserObj的类型
export class AuthStore {
userObj = {
name: 'zlz',
age: 23,
phone: '12345689'
}
setUserObj(obj: UserObj) {
this.userObj = obj;
}
}
根据以上使用场景需要实现一个工具函数——GetKeyType
// 利用InstanceType推导出类的类型;
type UserObj = GetKeyType<InstanceType<typeof AuthStore>, 'userObj'>
// K 是 GetKeyType 传入的第二个参数 且是T的子属性
type GetKeyType<T,K extends keyof T> = T[K]
export class AuthStore {
userObj = {
name: 'zlz',
age: 23,
phone: '12345689'
}
setUserObj(obj: UserObj) {
this.userObj = obj;
}
}
推导出来的类型如下
// interface UserObj{
// name: string
// age: number
// phone: string
// }
场景二
使用场景如下所示:我们有一个产品信息的泛型,但是之前迭代没有intruduce(产品介绍)这个字段;我们要兼容老数据
interface Product {
name: string
id: string
intruduce: string
...
}
实现方式一:
interface Product {
name: string
id: string
intruduce: string
}
interface NewProduct extends Omit<Product, 'intruduce'> {
intruduce?: string
}
实现方式二:
根据以上使用场景需要实现一个工具函数——SetPartial
ps:很明显方式二好些,工具函数可以复用,使用更加简便
type SetPartial<T,K extends keyof T> = Omit<T,K> & Partial<Pick<T, K>>
interface Product {
name: string
id: string
intruduce: string
}
type NewProduct = SetPartial<Product, 'intruduce' | 'id'>
得到的NewProduct
// interface NewProduct{
// name: string
// id?: string
// intruduce?: string
// }
场景三
使用场景如下所示:
[['a'], ['ee',['b', 'c']], ['d']]
转化为
type Result = "a" | "b" | "c" | "ee" | "d"
需要利用infer 和递归来实现一个工具类——NaiveFlat
type NaiveFlat<T extends any[]> = T extends (infer P)[] ? P extends any[] ? NaiveFlat<P> : P : never;
type Result = NaiveFlat<[['a'], ['ee',['b', 'c']], ['d']]>;
// type NaiveResult = "a" | "b" | "c" | "ee" | "d"
1.infer
TS的关键字:预判类型推导
T extends (infer P)[]
P 它可以是strng | number | null | undefined 这些基础类型
注意:infer只能用于在extends的地方
2. NaiveFlat执行过程
1. T 是 [['a'], ['ee',['b', 'c']], ['d']] ,然后T extends (infer P)[] ? P extends any[] ?都为真,执行 NaiveFlat<P>;
2. NaiveFlat<P>中的P是数组T中的每一个子元素,接下来执行NaiveFlat<['a']>;
3. T 是 ['a'],T extends (infer P)[]?为真,P extends any[]为假;
4. 让后直接返回P(p就是‘a’)
然后到2.重复执行...