TS类型体操

90 阅读1分钟

封装几个常用的 TypeScript 类型体操,并给出简单的例子供参考:

  1. 限制值域的类型
type ValueOf<T extends ReadonlyArray<unknown>> = T[number];

使用:

type Colors = ReadonlyArray<'red' | 'green' | 'blue'>;
type Color = ValueOf<Colors>; // 'red' | 'green' | 'blue'
  1. 限制对象的属性值类型
type PropertyOfType<T, U> = {
  [K in keyof T]: T[K] extends U ? K : never;
}[keyof T];

使用:

interface Person {
  name: string;
  age: number;
  location: string;
}

type StringKeys = PropertyOfType<Person, string>; // 'name' | 'location'
  1. 求取对象中某一属性的类型
type ValueOfKey<T, K extends keyof T> = T[K];

使用:

interface Person {
  name: string;
  age: number;
  location: string;
}

type Name = ValueOfKey<Person, 'name'>; // string
  1. 限制参数类型
type FirstParameter<T> = T extends (arg1: infer P, ...args: any[]) => any ? P : never;

使用:

function greet(name: string, age: number): void {
  console.log(`Hello, ${name}! You are ${age} years old.`);
}

type Name = FirstParameter<typeof greet>; // string

这里 Name 类型为 string,因为 greet 函数的第一个参数类型为 string

  1. 合并两个类型
type Merge<T, U> = Omit<T, keyof U> & U;

使用:

interface Person {
  name: string;
  age: number;
}

interface Employee {
  name: string;
  salary: number;
}

type EmployeeRecord = Merge<Person, Employee>; // { name: string; age: number; salary: number; }
  1. 获取函数返回值类型
type ReturnType<T extends (...args: any[]) => any> = T extends (...args: any[]) => infer R ? R : any;

使用:

function add(x: number, y: number): number {
  return x + y;
}

type Result = ReturnType<typeof add>; // number
  1. 将联合类型转换为交叉类型
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;

使用:

interface Person {
  name: string;
  age: number;
}

interface Employee {
  salary: number;
  position: string;
}

type EmployeePerson = Person & Employee;
type EmployeePersonUnion = Person | Employee;
type EmployeePersonIntersection = UnionToIntersection<EmployeePersonUnion>; // Person & Employee

这里 EmployeePersonUnionPersonEmployee 的联合类型,而 EmployeePersonIntersectionPersonEmployee 的交叉类型。

  1. 判断两个类型是否相等
type Equals<T, U> = T extends U ? (U extends T ? true : false) : false;

使用:

type Result1 = Equals<42, 42>; // true
type Result2 = Equals<{ a: number }, { a: number }>; // true
type Result3 = Equals<{ a: number }, { b: number }>; // false
  1. 排除类型中的某些属性
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

使用:

interface Person {
  name: string;
  age: number;
  location: string;
}

type PersonWithoutLocation = Omit<Person, 'location'>; // { name: string; age: number; }
  1. 从类型中排除 null 和 undefined
type NonNullable<T> = T extends null | undefined ? never : T;

使用:

type Foo = string | null | undefined | number;
type Bar = NonNullable<Foo>; // string | number

以上是一些常用的 TypeScript 类型体操,希望能对您有所帮助。