Skip to main content

TypeScript 范型

关键字

以下面 User 类型为例子

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

keyof

得到 object 类型的所有属性名构成的联合类型

type UserAttr = keyof User; // 'name' | 'age'

typeof

推导某实例的类型

const foo = () => ({ name: 'Simon', age: 18 });
type Foo = typeof foo; // () => { name: string, age: number }

extends

在类型运算中,不是继承或扩展,而是判断一个类型是否可以被赋予另一个类型。

type MustFunc =  Foo extends Function ? Foo : () => { a: 1 }

也可以用来类型约束

function logLength<T>(arg: T) {
console.log(arg.length); // 类型“T”上不存在属性“length”
}

// 改造成如下

interface LengthObj {
length: number
}
function logLength<T extends LengthObj>(arg: T) {
console.log(arg.length);
}

infer

类型提取

type UserPromise = Promise<User>;

type UnPromisify<T> = T extends Promise<infer V> ? V : never;
type InferedUser = UnPromisify<T>; // { name: string, age: number }

工具类型

Partial<T>Required<T>Readonly<T>Mutable<T>

Partial<T> 使得 object 类型的所有属性可选;

type MyPartial<T> = {
[k in keyof T]?: T[K];
}

Required<T> 使得 object 类型的所有属性必填;

type MyRequired<T> = {
[k in keyof T]-?: T[K];
}

Readonly<T> 使得 object 类型的所有属性只读;

type MyReadonly<T> = {
readonly [k in keyof T]: T[K];
}

Mutable<T> 使得 object 类型的所有属性可变;

type MyMutable<T> = {
-readonly [k in keyof T]: T[K];
}

Record<K, T>Pick<T, K>

Record<K, T> K 是任意联合类型、T 为任意类型,最后组合成一个 object 类型

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

type ABCObj = MyRecord<'a' | 'b' | 'c', number> // { a: number, b: number, c: number }

Pick<T, K> 是从 object 类型中,选取一些属性(属性的联合类型),组合成一个新的 object 类型

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

type NameObj = MyPick<User, 'name'>; // { name: string }

Exclude<T, U>Extract<T, U>NonNullable<T>

type MyExclude<T, U> = T extends U ? never : T;
type MyExtract<T, U> = T extends U ? T : never;
type MyNonNullable<T> = T extends null | undefined ? never : T;

Omit<T, K>

与 Pick 相反,用于排除某些键

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

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