TypeScript 工具泛型的使用
阿宅 / 2021-03-15 / 前端 / 阅读量 73

TypeScript 工具泛型的使用

1. Partial

作用:将传入的属性变为可选项

type Partial<T> = { [P in keyof T]?: T[P] };

使用举例:

type Person = {
  name: string;
  age: number;
}

type PartialPerson = Partial<Person>;

let partialPerson: PartialPerson = {
  name: 'tom'
};

// 实际上,就是把对象中所有的 key 转化为可选的。
type PartialPerson = {
  name?: string;
  age?: number;
}

2. Required

作用:将传入的属性变为必选项

type Required<T> = { [P in keyof T]-?: T[P] };

使用举例:

type Person = {
  name: string;
  age?: number;
}

type RequiredPerson = Required<Person>;

// error
let requiredPerson: RequiredPerson = {
  name: 'tom'
};

// 实际上,就是把对象中所有的 key 转化为必选的。
type RequiredPerson = {
  name: string;
  age: number;
}

3. Readonly

作用:将传入的属性变为只读的

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

使用举例:

type Person = {
    name: string;
    age: number;
}

type ReadonlyPerson = Readonly<Person>;

let readonlyPerson: ReadonlyPerson = {
    name: 'tom',
    age: 19,
};

// error
readonlyPerson.name = 'aaa';

// 实际上,就是把对象中所有的 key 转化为只读的。
type ReadonlyPerson = {
  readonly name: string;
  readonly age: number;
}

4. Pick

作用:从 T 中取出 一系列 K 的属性

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

使用举例:

type Person = {
    name: string;
    age: number;
}

type PickName = Pick<Person, 'name'>;

let person: PickName = {
    name: 'tom'
}

5. Record

作用:将 K 中所有的属性的值转化为 T 类型

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

使用举例:

type petsGroup = 'dog' | 'cat' | 'fish';
interface IPetInfo {
    name:string,
    age:number,
}

type IPets = Record<petsGroup, IPetInfo>;

const animalsInfo:IPets = {
    dog:{
        name:'dogName',
        age:2
    },
    cat:{
        name:'catName',
        age:3
    },
    fish:{
        name:'fishName',
        age:5
    }
}

6. Exclude

作用:从 T 中找出 U 中没有的元素, 换种更加贴近语义的说法其实就是从T 中排除 U

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

使用举例:

type T = Exclude<1 | 2, 1 | 3> // => 2

type Person = {
    name: string;
    age: number;
    sex: 'male' | 'female';
    money: number;
}

type ExcludeKey = Exclude<keyof Person, 'name' | 'age'>;

// type ExcludeType = Pick<Person, ExtractKey>;
type ExcludeType = Record<ExcludeKey, Person[ExcludeKey]>;

let person: ExcludeType = {
    sex: 'male',
    money: 0,
};

7. Extract

作用:提取出 T 包含在 U 中的元素, 换种更加贴近语义的说法就是从 T 中提取出 U

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

使用举例:

type Person = {
    name: string;
    age: number;
    sex: 'male' | 'female';
    money: number;
}

type ExtractKey = Extract<keyof Person, 'name' | 'age'>;

// type ExcludeType = Pick<Person, ExtractKey>;
type ExtractType = Record<ExtractKey, Person[ExtractKey]>;

let person: ExtractType = {
    name: 'tom',
    age: 19,
};

8. Omit

作用:忽略 T 对象中的 K 属性

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

使用举例:

type Person = {
    name: string;
    age: number;
    sex: 'male' | 'female';
    money: number;
}

// type ExcludeKey = Exclude<keyof Person, 'name' | 'age'>;
// type ExcludeType = Pick<Person, ExtractKey>;
type OmitType = Omit<Person, 'name' | 'age'>;

let person: OmitType = {
    sex: 'male',
    money: 0,
};

9. NonNullable

作用:从 T 中排除 null 和 undefined

type NonNullable<T> = T extends null | undefined ? never : T;

使用举例:

type SexType = 'male' | 'female' | null | undefined;
type NonNullableType = NonNullable<SexType>; // => 'male' | 'female'

10. Parameters

作用:获取一个函数 T 入参的类型

type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;

使用举例:

type Person = {
    name: string;
    age: number;
    sex: 'male' | 'female';
    money: number;
}

function getName(person: Person): string {
    return person.name;
}

type ParametersType = Parameters<typeof getName>; // => [Person]

11. ConstructorParameters

作用:获取 class T 构造函数的入参的类型

type ConstructorParameters<T extends new (...args: any) => any> = T extends new (...args: infer P) => any ? P : never;

使用举例:

class Person {
  private firstName: string;
  private lastName: string;
  
  constructor(firstName: string, lastName: string) {
      this.firstName = firstName;
      this.lastName = lastName;
  }
}

type P = ConstructorParameters<typeof Person>; // -> [string, string]

12. ReturnType

作用:获取函数 T 的返回类型

type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;

使用举例:

function foo(x: number): Array<number> {
  return [x];
}
type fn = ReturnType<typeof foo>; // => number[]

13. InstanceType

作用:获取 class T 构造函数的实例类型

type InstanceType<T extends new (...args: any) => any> = T extends new (...args: any) => infer R ? R : any;

使用举例:

class C {
  x = 0;
  y = 0;
}

type T0 = InstanceType<typeof C>; // C
type T1 = InstanceType<any>; // any
type T2 = InstanceType<never>; // any
type T3 = InstanceType<string>; // Error
type T4 = InstanceType<Function>; // Error