TS体操(待完成)
简单
实现Pick
首先需要知道Pick是什么
Pick,故名思意——挑选。在某个已经存在的类型T中选出指定一组属性K来创建新的类型
其应用
interface Person{
name:string,
age:number,
address:string
}
type PersonPick = Pick<Person, 'name'|'age'>
//相当于得到,
interface PersonPick{
name:string,
age:number
}
type Pick<T, k extends keyof T> = {
[P in K]:T[P]
}
其原理实现如上
对于[P in K]:T[P] ,相当于从K中取出每个属性P,然后新类型的相应属性类型T中对应键p属性值的类型
实现Readonly
Readonly可以声明只读属性,对于实现可读类型可以使用映射类型完成
type Readonly<T>={
readonly [P in keyof T] : T[P]
}
实现元组转化为对象
const tuple = ['a', 'b', 'c'] as const;
type TupleToObject<T extends readonly (keyof any)[]> = {
[P in T[number]]: P
}
//等同于下面这个
type Object = {a:'a',b:'b',c:'c'}
这里T extends readonly (keyof any)[] 相当于是,限制T必须为一个只读元组
[P in T[number]]这部分是采用了映射类型语法,它遍历T数组中的每一个元素,T[number] 表示类型T所有元素组成的联合类型(即可以任意访问数组中任意位置的元素)
后面的就是,对于 T 数组中的每个元素 P,我们在新创建的对象类型中声明一个同名属性,并将其类型设置为 P
找到第一个/最后一个类型
type First<T extends any[]> = T extends [infer P, ...any[]] ? P : never
type Last<T extends any[]> = T extends [...any[],infer P]?P:never
实现Exclude
type MyExclude<T,U> = T extends U ? never : T
如果T是U的子类型,或者T= =U那么返回never
如果 T 中有部分或全部成员不在 U 中,则结果类型将包含这些不在 U 中的 T 的成员
实现If效果
type A = If<true, 'a','b'>
type B = If<false, 'a','b'>
大概就是实现这个效果
实现代码
type If<B extends boolean, T, F> = C extends true ? T : F
实现concat
效果就是数组.concat(arr1)这样子
type Result = Concat<[1],[2]>
//得到结果是 [1,2]
具体实现很简单,直接将两者解构放在一个数组中就行
type Concat<T extends any[], S extends any[]> = [...T,...U]
实现Includes
includes其效果如下
type Includes<T extends readonly any[], U> = {
[K in T[number]]: true;
}[U] extends true? true : false;
-
[K in T[number]]: true 使用了映射类型(Mapped Type)的语法,它会遍历 T 中的所有元素类型(通过 T[number] 来获取),并为每个元素类型 K 创建一个新的属性,其属性值为 true。例如,如果 T = [string, number],则生成的类型会是 { string: true, number: true }。
-
[U] extends true? true:false,是利用索引访问操作符尝试从上一步生成的类型中获取属性U的值
中等
ReturnType
ReturnType的作用:获取函数的返回类型
其使用
function foo(x:string):number{
return parseInt(x)
}
type fooType = ReturnType<typeof foo>
其实现
type ReturnType<T> = T extends (...args:any[])=> infer R ? R : never
使用infer R进行推断函数中的返回类型,并将其赋值给R,然后得到的类型是R
实现Omit
Omit是什么?
Omit是一个内置工具,其作用是从一个已存在的对象类型T中剃除指定的属性键K,从而创建一个新的类型
其使用
type PersonOmiteKey = Omit<Person,'key'>
其原理实现
type MyOmit<T,U> = Pick<T, Exclude<keyof T, U>>
Pick和Exclude都可以手搓,结合上面的
可以实现
type MyPick<T, K extends keyof T> = {
[P in K]:T[P]
}
type MyExclude<T,U> = T extends U ? never : T;
type MyOmit<T,U> = MyPick<T,MyExclude<keyof T,U>>
深度Readonly
即将对象的每一个参数及其子对象递归地设为只读
type IsObject<T> = keyof T extends never ? false:true//判断是否可枚举
type DeepReadonly<T> = {
readonly [P in keyof T] : IsObject<T[P]> extends true?
DeepReadonly<T[P]>:
T[P]
}
事例:
type obj1 = {
name: string
age: number
address: string
hobby: [
string,
number
]
}
type obj2 = DeepReadonly<obj1>
/**
* type obj2 = {
readonly name: string;
readonly age: number;
readonly address: string;
readonly hobby: readonly [string, number];
}
*/
出堆
实现一个POP,接收一个数组并返回一个没有最后一个元素的数组
type arr1 = ['a','b','c']
type re1 = POP<arr1> //// expected to be ['a', 'b', 'c']
其实现如下
type POP<T extends any[]> = T extends [...infer L,infer R] ? R : never