interface Eg1 { name: string, readonly age: number } type T1=keyof Eg1//name|age classEg2{ private name: string, publicreadonly age:number, protected home:string } //T2被约束为age,非公有属性不能被keyof获取 type T2=keyof Eg2
T[k]索引查询:
1 2 3 4 5 6 7 8
interface Eg1 { name:string, readonly age: number, } type V1=Eg1['name']//string type V2=Eg1['name'|'age']//string | number type V3=Eg1['name'|'age222']//any type V4=Eg1[keyof Eg1]//strign | number
[]中的key有不存在于T中的,则是any
第一个元素类型:
1
type First<T extendsany[]> = T extends [infer F,...infer R] ? F : nerver
//key 为联合类型中的每个子类型,类型为T //keyof any得到的是string | number |symbol //类型key的类型只能为string | number | symbol type Record<K extends keyof any, T>={ //遍历key,将值设为T [P in K]:T } /*example: type Eg2 = {a:B,b:B}*/ interface A { a:string, b:number } interface B { key1: number, key2: string } type Eg2=Record<keyof A,B> /*Partial,Readonly,Pick同态,其实现需要输入类型T拷贝属性,因此属性修饰符例如readonly,?:会被拷贝*/ type Eg=Pick<{readonly a?: string},'a'> //keyof T 辅助拷贝传入类型的属性 //type Eg=<{readonly a?: string},'a'> type Pick<T,K extends keyof T>={ [P in K]:T[P] } /*在Pick中,P in keyof T,T为输入的类型,而keyof T则遍历了输入类型,而Record的实现中,并没有遍历输入的类型,K只是约束为keyof any的子类型*/
实现Readonly
1 2 3 4 5 6 7 8
type MyReadonly<T> = { readonly [P in keyof T]: T[P] } //example type Eg=MyReadonly<{ key1: string, key2: number }>
实现Pick:
1 2 3 4 5 6 7 8 9
type MyPick<T, K extends keyof T> = { [P in K]: T[P] } interface Todo{ title: string description: string completed: boolean } type A=MyPick<Todo,'title'| 'completed'>
Exclude:
1 2 3 4 5
/*遍历T中的所有子类型,如果该子类型约束于U(存在于U,兼容于U),则返回nerver类型,否则返回该子类型 */ type Exclude<T,U> = T extends U ? nerver : T //example: type Eg = 'key1' type Eg=Exclude<'key1'|'key2','key2'> //nerver表示一个不存在的类型,与其他类型联合后,是没有nerver的
Extract:
1 2
//提取联合类型T和U的交集 type Extract<T,U> = T extends U ? T : never
Omit:
1 2 3 4 5 6 7
//Omit<T,K>从类型T中剔除K中的所有属性 //用Pick实现 type Omit = Pick<T,Exclude<keyof T,K>> //利用映射类型 type Omit2<T,K extends keyof any> = { [P in Exclude<keyof T,K>]:T[P] }
Parameters和ReturnType
1 2 3 4 5 6 7 8 9
//Parameters获取函数参数类型,将每个参数类型放在一个元组 type Parameters<T extendsFunction> = T extends (...args: infer P)=>any ? P : never; //example type Eg = Parameters<(arg1:string,arg2:number) =>void> //type Eg=[arg1:string,arg2:number] /*Parameters约束参数T必须是个函数类型,具体实现就是判断T是否是函数类型,是就是要infer P让ts自己推到出函数的参数类型,并将推导结果存到类型P,否则 返回never*/ //ReturnType获取函数的返回值类型 type ReturnType<T extendsFunction> = T extends (...args: any)=> infer R ? R : never
//SymmetricDifference<T,U>获取没有同时存在于T和U内的类型 type SymmetricDifference<T,U>=Exclude<T|U,T&U> //example:type Eg ='1' | '4' type Eg = SymmetricDifference<'1'|'2'|'3','2'|'3'|'4'>
FunctionKeys:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
//获取T中所有类型为函数的key组成的联合类型 type NonUndefined<T>= T extendsundefined ? nerver : T type FunctionKeys<T extendsobject> = { [K in keyof T]: NonUndefined<T[K]> extends FunctionKeys ? K : nerver }[keyof T] /** * @example * type Eg = 'key2' | 'key3'; */ type AType = { key1: string, key2: () =>void, key3: Function, }; type Eg = FunctionKeys<AType>; //最后经过{省略}[keyof T]索引访问,取到的为值类型的联合类型never | key2 | key3,计算后就是key2 | key3; /*T[]是索引访问操作,可以取到值的类型,T['a'|'b']可以依次取到值的类型进行联合, T[keyof T]则是取到T所有值的类型类型 nerver和其他类型进行联合时,nerver不存在,nerver | number | string = number | string */
OptionalKeys:
1 2 3 4 5 6 7 8 9 10 11
//OptionalKeys提取T中所有可选类型的key组成的联合类型 /*用映射类型遍历所有key,通过Pick<T,P>提取当前key和类型,利用同态拷贝会拷贝可选修饰符的特性,利用{}extends {当前key:类型} 判断是否是可选类型*/ type OptionalKeys<T> = { [P in keyof T]: {} extends Pick<T,P> ? P : nerver }[keyof T]
type Eg = OptionalKeys<{key1?: string, key2: number}> //{key1?:string} //利用{}extends {当前key:类型} 判断是否是可选类型,{}和只包含可选参数类型{key1?:string}是兼容这一特性,extends前面的{}替换为object也可以 type Eg2={} extends {key1:string} ? true : false//false type Eg3={} extends {key1?:string} ? true : false//true
增强Pick:
PickByValue
1 2 3 4 5 6 7 8 9 10 11 12 13
//PickByValue提取指定类型的键值对 //获取T中类型不为nerver的类型组成大的联合类型 type TypeKeys<T> = T[keyof T] type PickByValue<T,V> = Pick<T, TypeKeys<{[P in keyof T]: T[P] extends V ? P : nerver}> > /*example type Eg = { key1: number; key3: number }*/ type Eg = PickByValue<{key1:number,key2:string,key3:number},number>
PickByValueExtract:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
//Ts类型兼容的原因,string可以分配给string|number type PickByValueExact<T,V>=Pick<T, TypeKeys<{[P in keyof T]: [T[P]] extends [V]} ? ([V] extends [T[P]] ? P : never) : never > > //type Eg={b:number} type Eg1=PickByValueExact<{a:string,b:number},number> type Eg2=PickByValueExact<{a:string,b:number,c:number|undefined},number> //type Eg2={b:number,c:number|undefined} /*给泛型套一层元组,规避extends的分发式联合类型的特性 利用两个类型互相兼容的方式判断是否相同*/ //example type Eq1<X,Y> = X extends Y ? true : false type Eq2<X,Y> = [X] extends [Y] ? true : false type Eq3<X,Y>= [X] extends [Y] ? ([Y] extends [X] ? true : false) : false
增强Omit:
1 2 3 4 5 6 7
//Omit<T,K>从类型T中剔除K中的所有属性 //用Pick实现 type Omit = Pick<T,Exclude<keyof T,K>> //利用映射类型 type Omit2<T,K extends keyof any> = { [P in Exclude<keyof T,K>]:T[P] }
OmitByValue:
1 2 3 4 5 6 7 8 9 10
type TypeKeys<T> = T<keyof T> type OmitByValue<T,V> = Omit<T, TypeKeys<{[P in keyof T] : T[P] extends V ? P : never}> >
type OmitByValueExact<T,V> =Omit<T, TypeKeys<{[P in keyof T]: [T[P]] extends [V] ?([V] extends [T[P]] ? [T[P]] : never) : never }>
functionmyMap(fn,context){ if(typeof fn !== 'function'){ thrownewError("this first argument must be a function") } let res=[] let arr=this for(let i=0;i<arr.length;i++){ res[i]=fn.call(context,arr[i],i,arr) } return res }