Partial<T>
Partial
用于将类型中所有属性变为可选类型:
interface Todo {
title: string;
description: string;
}
const todo1: Todo = {
title: "organize desk",
description: "clear clutter",
};
const todo2: Partial<Todo> = {
description: "throw out trash",
};
实现源码:
type Partial<T> = {
[P in keyof T]?: T[P];
};
Required<T>
Required
用于将类型所有属性变为必需类型:
interface Props {
a?: number;
b?: string;
}
const obj: Props = { a: 5 }; // OK
const obj2: Required<Props> = { a: 5 }; // Error: property 'b' missing
实现源码:
type Required<T> = {
[P in keyof T]-?: T[P];
};
Readonly<T>
Readonly
用于将类型中所有属性变成只读类型:
interface Todo {
title: string;
}
const todo: Readonly<Todo> = {
title: "Delete inactive users"
};
todo.title = "Hello"; // Error: cannot reassign a readonly property
实现源码:
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
Record<T, K>
Record
用于将T
中所有的属性转换为K
类型:
interface PageInfo {
title: string;
}
type Page = "home" | "about" | "contact";
const x: Record<Page, PageInfo> = {
about: { title: "about" },
contact: { title: "contact" },
home: { title: "home" },
};
实现源码:
type Record<K extends keyof any, T> = {
[P in K]: T;
};
Exclude<T, K>
Exclude
用于筛选所有在T
中,但不在K
中的属性:
type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"
type T1 = Exclude<"a" | "b" | "c", "a" | "b">; // "c"
type T2 = Exclude<string | number | (() => void), Function>; // string | number
实现源码:
type Exclude<T, U> = T extends U ? never : T;
Extract<T, K>
Extract
和Exclude
有些类似,用于筛选既在T
中,又在K
中的属性:
type T0 = Extract<"a" | "b" | "c", "a" | "f">; // "a"
type T1 = Extract<string | number | (() => void), Function>; // () => void
实现源码:
type Extract<T, U> = T extends U ? T : never;
Pick<T, K>
Pick
用于返回从T
中筛选出K
包含的属性所组成的类型:
interface Todo {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = Pick<Todo, "title" | "completed">;
const todo: TodoPreview = {
title: "Clean room",
completed: false,
};
实现源码:
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
Omit<T, K>
和Pick
相反,忽略K
中包含的属性:
interface Todo {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = Omit<Todo, "description">;
const todo: TodoPreview = {
title: "Clean room",
completed: false
};
实现源码:
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
可以看到,Omit
类型就是对之前提到的Pick
和Exclude
的进一步封装。
NonNullable<T>
NonNullable
用于筛选出T
中不是null
或者undefined
的所有类型:
type T0 = NonNullable<string | number | undefined>; // string | number
type T1 = NonNullable<string[] | null | undefined>; // string[]
实现源码:
type NonNullable<T> = T extends null | undefined ? never : T;
Parameters<T>
Parameters
用于筛选函数所有的参数类型,并返回一个由这些参数类型构成的元组:
type T0 = Parameters<() => string>; // []
type T1 = Parameters<(s: string) => void>; // [string]
type T2 = Parameters<<T>(arg: T) => T>; // [unknown]
实现源码:
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
可以看到T
被约束必须为函数类型,如果传入一个非函数类型会报错。
ReturnType<T>
ReturnType
用于获取函数返回值类型:
type T0 = ReturnType<() => string>; // string
type T1 = ReturnType<(s: string) => void>; // void
type T2 = ReturnType<<T>() => T>; // unknown
type T3 = ReturnType<<T extends U, U extends number[]>() => T>; // number[]
实现源码:
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
T
同样被约束必须为函数类型。
ConstructorParameters<T>
ConstructorParameters
和Parameters
十分相似,用于获取构造函数的所有参数类型:
class Person {
constructor(name: string, age: number) {}
}
type T0 = ConstructorParameters<typeof Person>; // [string, number]
实现源码:
type ConstructorParameters<T extends new (...args: any) => any> = T extends new (...args: infer P) => any ? P : never;
T
被约束为必须为构造函数。
InstanceType<T>
InstanceType
用于获取构造函数的返回值:
class Person {
constructor(name: string, age: number) {}
}
type T0 = InstanceType<typeof Person>; // Person
实现源码:
type InstanceType<T extends new (...args: any) => any> = T extends new (...args: any) => infer R ? R : any;
T
同样被约束为必须为构造函数。
ThisParameterType<T>
ThisParameterType
用于获取函数的this
参数类型。如果函数未指定this
参数,返回unknown
,需要开启strictFunctionTypes
才能工作:
function toHex(this: Number) {
return this.toString(16);
}
type T0 = ThisParameterType<typeof toHex>; // Number
实现源码:
type ThisParameterType<T> = T extends (this: infer U, ...args: any[]) => any
? U
: unknown;
OmitThisParameter<T>
OmitThisParameter
用于删除函数中的this
参数,需要开启strictFunctionTypes
才能工作:
function toHex(this: Number, others: any) {
return this.toString(16);
}
type T0 = typeof toHex; // function toHex(this: Number, others: any): string
type T1 = OmitThisParameter<typeof toHex>; // (others: any) => string
实现源码:
type OmitThisParameter<T> = unknown extends ThisParameterType<T>
? T
: T extends (...args: infer A) => infer R
? (...args: A) => R
: T;
ThisType<T>
ThisType
并不会转换类型,而是用于标记函数中this
的类型,类似于指定this
参数。需要开启noImplicitThis
才能工作:
type ObjectDescriptor<D, M> = {
data?: D;
methods?: M & ThisType<D & M>; // 标记方法的this类型
};
function makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & M {
let data: object = desc.data || {};
let methods: object = desc.methods || {};
return { ...data, ...methods } as D & M;
}
let obj = makeObject({
data: { x: 0, y: 0 },
methods: {
moveBy(dx: number, dy: number) {
this.x += dx; // ts能识别this类型
this.y += dy;
}
}
});
methods
使用ThisType
指定this
。所以makeObject
函数调用时,ts就能推断出methods
中的函数this
类型为{ x: number, y: number } & { moveBy(dx: number, dy: number): number }
。
在源码中,ThisType
就是一个空的泛型接口。