跟着 小满zs 学 ts:学习TypeScript24(TS进阶用法-泛型工具)_ts泛型工具-CSDN博客
- Partial 所有属性可选的意思
- Required 所有属性必选的意思
- Pick 提取部分属性
- Exclude 排除部分属性
- emit 排除部分属性并且返回新的类型
Partial
属性变为可选。
interface User {
address?: string
name: string
age: number
}
type PartialUser = CustomPartial<User>
// 原理
type CustomPartial<T> = {
// in 操作符后面只能跟联合类型
[P in keyof T]?: T[P]
}
Required
属性全部变为必选。
interface User {
address?: string
name: string
age: number
}
type RequiredUser = Required<User>
// 原理
type CustomRequired<T> = {
// in 操作符后面只能跟联合类型
[P in keyof T]-?: T[P]
}
注意这里是
-?
,而不是直接去掉喔~
Pick
提取属性类型。
interface User {
address?: string
name: string
age: number
}
// 从 User 中选择出 name 和 age 属性
type PickUser = Pick<User, 'name' | 'age'>
// 原理
type CustomPick<T, K extends keyof T> = {
// in 操作符后面只能跟联合类型
[P in K]: T[P]
}
Exclude
排除某个 / 某些类型。
interface User {
address?: string
name: string
age: number
}
// Exclude 排除的是联合类型 而不是 interface
type ExcludeUser = Exclude< 'name' | 'age' | 'address', 'name' | 'age'>
// 原理
// 这里使用 never 是因为 never 在联合类型中会被排除掉的
type CustomExclude<T, K> = T extends K ? never : T
这里有一个知识点需要注意。
以下来自:TS关键字extends用法总结 - 掘金 (juejin.cn)
对于使用extends关键字的条件类型(即上面的三元表达式类型),如果extends前面的参数是一个泛型类型,当传入该参数的是联合类型,则使用分配律计算最终的结果。分配律是指,将联合类型的联合项拆成单项,分别代入条件类型,然后将每个单项代入得到的结果再联合起来,得到最终的判断结果。
还是用上面的例子说明
type P<T> = T extends 'x' ? string : number;
type A3 = P<'x' | 'y'> // A3的类型是 string | number
该例中,extends的前参为T,T是一个泛型参数。在A3的定义中,给T传入的是’x’和’y’的联合类型'x' | 'y'
,满足分配律,于是’x’和’y’被拆开,分别代入P<T>
P<'x' | 'y'> => P<'x'> | P<'y'>
'x’代入得到
'x' extends 'x' ? string : number => string
'y’代入得到
'y' extends 'x' ? string : number => number
然后将每一项代入得到的结果联合起来,得到string | number
总之,满足两个要点即可适用分配律:第一,参数是泛型类型,第二,代入参数的是联合类型
Omit
排除属性。
interface User {
address?: string
name: string
age: number
}
// 排除属性
type OmitUser = Omit<User, 'age' | 'address'>
// 原理
type CustomOmit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
Exclude
是针对联合类型,用于排除一些特定成员类型;Omit
是针对对象类型,用于忽略或排除某些特定属性;
Record
约束对象的 key 和 value。
type key = 'c'|'x'| 'k'
type value = '唱' | '跳' | 'rap' | '篮球'
let obj: Record<key, value> = {
// key 不能缺 value 随意
c: '唱',
x: 'rap',
k: 'rap'
}
并且支持嵌套,value 还可以是 Record<key, value>
。
// 原理
// 对象的 key 只能是 string | number | symbol
type ObjKey = keyof any
type CustomRecord<K extends ObjKey, V> = {
[P in K]: V
}
returnType
获取函数的返回值的类型。
const fn = () => {
return [1, 23, 34]
}
type arrNum = ReturnType<typeof fn>
// 原理
type CustomReturnType<T extends Function> = T extends (...args: any[]) => infer R ? R : any