Skip to content

TypeScript 常见类型工具

Awaited<Type>

Awaited<Type>用来取出 Promise 的返回值类型,适合用在描述then()方法和 await 命令的参数类型。

ts
// e.g.
type A = Awaited<Promise<string>>; // number
type C = Awaited<boolean | Promise<number>>; // number | boolean
ts
type Awaited<T> =
    T extends null | undefined ? T :
    T extends object & {
        then(
        onfulfilled: infer F,
         ...args: infer _
        ): any;
    } ? F extends (
    	value: infer V,
        ...args: infer _
    ) => any ? Awaited<V> : never:
    T;

如果 T 是 null 或 undefined,则返回 T。 如果 T 是一个对象类型且具有 then 方法,那么提取 then 方法的参数类型为 F。 如果 F 是一个函数类型,且该函数接受一个 value 参数,返回 any 类型,那么提取 value 参数的类型为 V。 如果 V 是一个函数类型,那么递归地应用 Awaited2<V>。 否则,返回 never。 如果上述条件都不满足,返回 T。

ConstructorParameters<Type>

ConstructorParameters<Type>提取构造方法Type的参数类型,组成一个元组类型返回。

ts
// e.g.
type T1 = ConstructorParameters<
  new (x: string, y: number) => object
>; // [x: string, y: number]
  
type T2 = ConstructorParameters<
  new (x?: string) => object
>; // [x?: string | undefined]
ts
type ConstructorParameters<
  T extends abstract new (...args: any) => any 
> = T extends abstract new (...args: infer P)
=> any ? P : never

ConstructorParameters<T> 是一个类型别名,它接受一个泛型参数 T,该参数限制为一个抽象类的构造函数类型。 T extends abstract new (...args: any) => any:这个条件限制泛型参数 T 必须是一个构造函数类型,且是抽象类的构造函数。...args: any 表示这个构造函数可以接受任意数量的参数。 T extends abstract new (...args: infer P) => any ? P : never:如果 T 满足上述条件,那么使用 infer P 提取构造函数的参数类型,将其赋值给类型 P。 如果条件成立,返回 P,即构造函数的参数类型。 否则,返回 never,表示不满足类型约束。

Exclude<UnionType, ExcludedMembers>

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

Extract<Type, Union>

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

InstanceType<Type>

InstanceType<Type>提取构造函数的返回值的类型(即实例类型),参数Type是一个构造函数,等同于构造函数的ReturnType<Type>

ts
// e.g.
type T = InstanceType<new () => object>; // object
type A = InstanceType<ErrorConstructor>; // Error
type B = InstanceType<FunctionConstructor>; // Function
type C = InstanceType<RegExpConstructor>; // RegExp
ts
type InstanceType<
  T extends abstract new (...args: any) => any
> = T extends abstract new (...args: any) => infer P
  ? P
  : never;

InstanceType<T> 是一个类型别名,它接受一个泛型参数 T,该参数限制为一个抽象类的构造函数类型。 T extends abstract new (...args: any) => any:这个条件限制泛型参数 T 必须是一个构造函数类型,且是抽象类的构造函数。...args: any 表示这个构造函数可以接受任意数量的参数。 T extends abstract new (...args: any) => infer P ? P : never:如果 T 满足上述条件,那么使用 infer P 提取构造函数的实例类型,将其赋值给类型 P。 如果条件成立,返回 P,即构造函数的实例类型。 否则,返回 never,表示不满足类型约束。

NonNullable<Type>

NonNullable<Type>用来从联合类型Type删除null类型和undefined类型,组成一个新类型返回,也就是返回Type的非空类型版本。

ts
// e.g.
type T1 = NonNullable<string|number|undefined>; // string|number
type T2 = NonNullable<string[]|null|undefined>; // string[]
type T3 = NonNullable<boolean>; // boolean
type T4 = NonNullable<number|null>; // number
type T5 = NonNullable<string|undefined>; // string
type T6 = NonNullable<null|undefined>; // never
ts
type NonNullable<T> = T & {}

T & {}等同于求T & Object的交叉类型。由于 TypeScript 的非空值都属于Object的子类型,所以会返回自身;而null和undefined不属于Object,会返回never类型。

Pick<Type, Keys>

Pick<Type, Keys>返回一个新的对象类型,第一个参数Type是一个对象类型,第二个参数Keys是Type里面被选定的键名。

ts
// e.g.
interface A {
  x: number;
  y: number;
}

type T1 = Pick<A, 'x'>; // { x: number }
type T2 = Pick<A, 'y'>; // { y: number }
type T3 = Pick<A, 'x'|'y'>;  // { x: number; y: number }
ts
type Pick<T, U extends keyof T> = {
  [K in U]: T[K]
}

Omit<Type, Keys>

Omit<Type, Keys>用来从对象类型Type中,删除指定的属性Keys,组成一个新的对象类型返回。

ts
// e.g.
interface A {
  x: number;
  y: number;
}

type T1 = Omit<A, 'x'>;       // { y: number }
type T2 = Omit<A, 'y'>;       // { x: number }
type T3 = Omit<A, 'x' | 'y'>; // { }
ts
type Omit<T, K extends keyof any> 
  = Pick<T, Exclude<keyof T, K>>;

ThisParameterType<Type>

ThisParameterType<Type>提取函数类型中this参数的类型。

ts
// e.g.
function toHex(this: Number) {
  return this.toString(16);
}

type T = ThisParameterType<typeof toHex>; // number
ts
type ThisParameterType<T> = 
 T extends (
  this: infer P,
  ...args: any
 ) => any ? P : never

OmitThisParameter<Type>

OmitThisParameter<Type>从函数类型中移除 this 参数。

ts
// e.g.
function toHex(this: Number) {
  return this.toString(16);
}

type T = OmitThisParameter<typeof toHex>; // () => string
ts
type OmitThisParameter<T> =
  unknown extends ThisParameterType<T> ? T :
  T extends (...args: infer A) => infer R ?
  (...args: A) => R : T;

unknown extends ThisParameterType<T> ? T : ...:这个条件判断 T 是否具有 this 参数。ThisParameterType<T> 是一个 TypeScript 4.1 引入的内置条件类型,用于获取函数类型 T 的 this 参数的类型。

如果 T 不具有 this 参数,返回 T 本身。 否则,继续下面的条件判断。 T extends (...args: infer A) => infer R ? ...:这个条件判断 T 是否是一个函数类型。

如果是,使用 infer A 获取函数参数的类型,赋值给类型 A。 使用 infer R 获取函数返回值的类型,赋值给类型 R。 最后,返回一个新的函数类型,参数类型为 A,返回值类型为 R。 (...args: A) => R : T:这个部分在上述条件都不满足时返回原始的类型 T。

Parameters<Type>

Parameters<Type>从函数类型Type里面提取参数类型,组成一个元组返回。

ts
// e.g.
type T1 = Parameters<() => string>; // []
type T2 = Parameters<(s:string) => void>; // [s:string]
type T3 = Parameters<<T>(arg: T) => T>;    // [arg: unknown]
type T4 = Parameters<
  (x:{ a: number; b: string }) => void
>; // [x: { a: number, b: string }]
type T5 = Parameters<
  (a:number, b:number) => number
>; // [a:number, b:number] 
type T1 = Parameters<string>; // 报错
type T2 = Parameters<Function>; // 报错
ts
type Parameters2<T extends (...args: any) => any> =
  T extends (...args: infer P) => any ? 
  P : never

Partial<Type>

Partial<Type>返回一个新类型,将参数类型Type的所有属性变为可选属性。

ts
// e.g.
interface A {
  x: number;
  y: number;
}
 
type T = Partial<A>; // { x?: number; y?: number; }
ts
type Partial<T> = {
  [P in keyof T]?: T[P];
};

Readonly<Type>

Readonly<Type>返回一个新类型,将参数类型Type的所有属性变为只读属性。

ts
// e.g.
interface A {
  x: number;
  y?: number;
}

// { readonly x: number; readonly y?: number; }
type T = Readonly<A>;
ts
type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};

Record<Keys, Type>

Record<Keys, Type>返回一个对象类型,参数Keys用作键名,参数Type用作键值类型。

ts
// e.g.
type T = Record<'a', number>; // { a: number }
type T = Record<'a'|'b', number>; // { a: number, b: number }
type T = Record<'a', number|string>; // { a: number|string }
ts
type Record<K extends string|number|symbol, T>
  = { [P in K]: T; }

Required<Type>

Required<Type>返回一个新类型,将参数类型Type的所有属性变为必选属性。它与Partial<Type>的作用正好相反。

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

ReadonlyArray<Type>

ReadonlyArray<Type>用来生成一个只读数组类型,类型参数Type表示数组成员的类型。

ts
// e.g.
const values: ReadonlyArray<string> = ['a', 'b', 'c'];

values[0] = 'x'; // 报错
values.push('x'); // 报错
values.pop(); // 报错
values.splice(1, 1); // 报错
ts
type MyReadonlyArray<Type> = {
  readonly length: number;
  readonly [index: number]: Type;
};

ReturnType<Type>

ReturnType<Type>提取函数类型Type的返回值类型,作为一个新类型返回。

ts
// e.g.
type T1 = ReturnType<() => string>; // string
type T2 = ReturnType<() => {
  a: string; b: number
}>; // { a: string; b: number }
type T3 = ReturnType<(s:string) => void>; // void
type T4 = ReturnType<() => () => any[]>; // () => any[]
type T5 = ReturnType<typeof Math.random>; // number
type T6 = ReturnType<typeof Array.isArray>; // boolean
ts
type ReturnType<T extends (...args: any) => any> = 
  T extends (...args: any) => infer P ?
  P : never

字符串类型工具

ts
Uppercase<StringType> // 将字符串类型的每个字符转为大写。
Lowercase<StringType> // 将字符串的每个字符转为小写。
Capitalize<StringType>// 将字符串的第一个字符转为大写。
Uncapitalize<StringType> // 将字符串的第一个字符转为小写。

Released under the MIT License.