ts工具类实现

91 阅读2分钟

Partial

Partial<T>T的所有属性变成可选的。

/*核心实现就是通过映射类型遍历T上所有的属性,然后将每个属性设置为可选属性*/
type Partial<T> = { [P in keyof T]?: T[P]; }
//改造
type PartialOptional<T, K extends keyof T> = { [P in K]?: T[P]; }
/** * @example * type Eg1 = { key1?: string; key2?: number } */ 
type Eg1 = PartialOptional<{ key1: string, key2: number, key3: '' }, 'key1' | 'key2'>;

Readonly

type Readonly<T> = { readonly [P in keyof T]: T[P] }

Pick

type Pick<T, K extends keyof T> = { [P in K]: T[P]; };

Record

构造一个type,key是第一个参数联合类型中的每一个子类型,类型就是第二个参数

/** 
* @example 
* type Eg1 = {
*  a: { key1: string; }; 
*  b: { key1: string; }; 
* } 
* @desc 就是遍历第一个参数'a' | 'b'的每个子类型,然后将值设置为第二参数 
*/ 
type Eg1 = Record<'a' | 'b', {key1: string}>
//具体实现
type Record<K extends keyof any, T> = { [P in K]: T }
  • 值得注意的是keyof any得到的是string | number | symbol
  • 原因在于类型key的类型只能为string | number | symbol
Exclude

Exclude<T, U>提取存在于T,但不存在于U的类型组成的联合类型。

type Exclude<T, U> = T extends U ? never : T;

Record

构造一个type,key是第一个参数联合类型中的每一个子类型,类型就是第二个参数

type Exclude<T, U> = T extends U ? never : T;
/** 
* @example 
* type Eg = 'key1' 
*/ 
type Eg = Exclude<'key1' | 'key2', 'key2'>

Extract

Extract<T, U>提取联合类型T和联合类型U的所有交集。

type Extract<T, U> = T extends U ? T : never;

Omit原理解析

Omit<T, K>从类型T中剔除K中的所有属性。

type Omit = Pick<T, Exclude<keyof T, K>>;

Parameters 和 ReturnType

Parameters 获取函数的参数类型,将每个参数类型放在一个元组中 ReturnType 获取函数的返回值类型。

  • infer关键词只能在extends条件类型上使用,不能在其他地方使用。
  • 只能在正确的分支上
/** 
* @desc 具体实现 
*/ 
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
/** 
* @example * type Eg = [arg1: string, arg2: number]; 
*/ 
type Eg = Parameters<(arg1: string, arg2: number) => void>;
/** 
* @desc ReturnType的实现其实和Parameters的基本一样 
* 无非是使用infer R的位置不一样。 
*/ 
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;

扩展:infer实现一个推导数组所有元素的类型:

/** 
* 约束参数T为数组类型, 
* 判断T是否为数组,如果是数组类型则推导数组元素的类型 
*/ 
type FalttenArray<T extends Array<any>> = T extends Array<infer P> ? P : never; 
/** 
* type Eg1 = number | string; 
*/ 
type Eg1 = FalttenArray<[number, string]> 
/** 
* type Eg2 = 1 | 'asd'; 
*/ 
type Eg2 = FalttenArray<[1, 'asd']>

自定义类型

SymmetricDifference

SymmetricDifference<T, U>获取没有同时存在于T和U内的类型。

type SymmetricDifference<T, U> = Exclude<T | U, T & U>;
  • Exclude第一个参数则是T | U,这是利用在联合类型在extends中的分发特性,可以理解为Exclude<T, T & U> | Exclude<U, T & U>;

[参考]愣锤(juejin.cn/post/699410…)