# 1. Partial

Partial<T> 的作用就是将某个类型里的属性全部变为可选项 ?

定义:

// node_modules/typescript/lib/lib.es5.d.ts

/**
 * Make all properties in T optional
 */
type Partial<T> = {
    [P in keyof T]?: T[P];
};
1
2
3
4
5
6
7
8

在以上代码中,首先通过 keyof T 拿到 T 的所有属性名,然后使用 in 进行遍历,将值赋给 P,最后通过 T[P] 取得相应的属性值。中间的 ?,用于将所有属性变为可选。

示例:

interface Todo {
  title: string;
  description: string;
}

function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {
  return { ...todo, ...fieldsToUpdate };
}

const todo1 = {
  title: "organize desk",
  description: "clear clutter"
};

const todo2 = updateTodo(todo1, {
  description: "throw out trash"
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 2. Required

Required 的作用刚好跟 Partial 相反,Partial 是将所有属性改成可选项,Required 则是将所有类型改成必选项。

定义:

// node_modules/typescript/lib/lib.es5.d.ts

/**
 * Make all properties in T required
 */
type Required<T> = {
    [P in keyof T]-?: T[P];
};
1
2
3
4
5
6
7
8

以上代码中,-? 的作用就是移除可选项 ?

与之对应的还有个 +? , 这个含义自然与 -? 之前相反, 它是用来把属性变成可选项的,+ 可省略,见 Partial

示例:

interface Props {
  a?: number;
  b?: string;
}

const obj: Props = { a: 5 }; // OK
const obj2: Required<Props> = { a: 5 }; // Error: property 'b' missing
1
2
3
4
5
6
7

# 3. Readonly

Readonly<T> 的作用是将某个类型所有属性变为只读属性,也就意味着这些属性不能被重新赋值。

定义:

// node_modules/typescript/lib/lib.es5.d.ts

/**
 * Make all properties in T readonly
 */
type Readonly<T> = {
    readonly [P in keyof T]: T[P];
};
1
2
3
4
5
6
7
8

给子属性添加 readonly 的标识,如果将上面的 readonly 改成 -readonly, 就是移除子属性的 readonly 标识。

示例:

interface Todo {
  title: string;
}

const todo: Readonly<Todo> = {
  title: "Delete inactive users"
};

todo.title = "Hello"; // Error: cannot reassign a readonly property
1
2
3
4
5
6
7
8
9

Readonly<T> 对于表示在运行时将赋值失败的表达式很有用(比如,当尝试重新赋值冻结对象的属性时)。

function freeze<T>(obj: T): Readonly<T>;
1

# 4. Record

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

定义:

// node_modules/typescript/lib/lib.es5.d.ts

/**
 * Construct a type with a set of properties K of type T
 */
type Record<K extends keyof any, T> = {
    [P in K]: T;
};
1
2
3
4
5
6
7
8

示例:

Record 通常用于描述一个对keyvalue 类型都有明确约束的对象,比方说,我们要求一个对象的 key 只能为 "home" | "about" | "contact" 其中一种,value 只能为 PageInfo 类型, 那么我们进行如下定义:

interface PageInfo {
  title: string;
}

type Page = "home" | "about" | "contact";

const x: Record<Page, PageInfo> = {
  about: { title: "about" },
  contact: { title: "contact" },
  home: { title: "home" }
};
1
2
3
4
5
6
7
8
9
10
11

# 5. Pick

Pick 的作用是将某个类型中的某些子属性挑出来,变成包含这个类型部分属性的子类型。

定义:

// node_modules/typescript/lib/lib.es5.d.ts

/**
 * From T, pick a set of properties whose keys are in the union K
 */
type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
};
1
2
3
4
5
6
7
8

示例:

interface Todo {
  title: string;
  description: string;
  completed: boolean;
}

type TodoPreview = Pick<Todo, "title" | "completed">;

const todo: TodoPreview = {
  title: "Clean room",
  completed: false
};
1
2
3
4
5
6
7
8
9
10
11
12

# 6. Omit

Omit 的作用刚好跟 Pick 相反,Pick 是从一个类型中挑选出某些类型,而 Omit 则是从一个类型中剔除掉某些类型。

定义:

// node_modules/typescript/lib/lib.es5.d.ts

/**
 * Construct a type with the properties of T except for those in type K.
 */
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
1
2
3
4
5
6

示例:

interface Todo {
  title: string;
  description: string;
  completed: boolean;
}

type TodoPreview = Omit<Todo, "description">;

const todo: TodoPreview = {
  title: "Clean room",
  completed: false
};
1
2
3
4
5
6
7
8
9
10
11
12

# 7. Exclude

Exclude<T, U> 的作用是剔除掉 T 包含在 U 中的元素,换种更加贴近语义的说法就是从 T 中剔除出 U

定义:

// node_modules/typescript/lib/lib.es5.d.ts

/**
 * Exclude from T those types that are assignable to U
 */
type Exclude<T, U> = T extends U ? never : T;
1
2
3
4
5
6

以上语句的意思就是 如果 T 能赋值给 U 类型的话,那么就会返回 never 类型,否则返回 T,最终结果是将 T 中的某些属于 U 的类型移除掉。

示例:

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
1
2
3

# 8. Extract

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

定义:

// node_modules/typescript/lib/lib.es5.d.ts

/**
 * Extract from T those types that are assignable to U
 */
type Extract<T, U> = T extends U ? T : never;
1
2
3
4
5
6

以上语句的意思就是 如果 T 能赋值给 U 类型的话,那么就会返回 T 类型,否则返回 never,最终结果是将 TU 中共有的属性提取出来。

示例:

type T01 = Extract<'a' | 'b' | 'c' | 'd', 'a' | 'c' | 'f'>;  // -> 'a' | 'c'
1

可以看到 T'a' | 'b' | 'c' | 'd' ,然后 U'a' | 'c' | 'f' ,返回的新类型就可以将 TU 中共有的属性提取出来,也就是 'a' | 'c' 了。

# 9. NonNullable

NonNullable 的作用是用来过滤类型中的 nullundefined 类型。

定义:

// node_modules/typescript/lib/lib.es5.d.ts

/**
 * Exclude null and undefined from T
 */
type NonNullable<T> = T extendsnull | undefined ? never : T;
1
2
3
4
5
6

示例:

type T0 = NonNullable<string | number | undefined>; // string | number
type T1 = NonNullable<string[] | null | undefined>; // string[]
1
2

# 10. ReturnType

ReturnType 的作用是用于获取函数的返回类型。

定义:

// node_modules/typescript/lib/lib.es5.d.ts

/**
 * Obtain the return type of a function type
 */
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
1
2
3
4
5
6

示例:

type T0 = ReturnType<() =>string>; // string
type T1 = ReturnType<(s: string) =>void>; // void
type T2 = ReturnType<<T>() => T>; // {}
type T3 = ReturnType<<T extends U, U extendsnumber[]>() => T>; // number[]
type T4 = ReturnType<any>; // any
type T5 = ReturnType<never>; // any
type T6 = ReturnType<string>; // Error
type T7 = ReturnType<Function>; // Error
1
2
3
4
5
6
7
8

# 11. Parameters

Parameters 的作用是用于获得函数的参数类型组成的元组类型。

定义:

// node_modules/typescript/lib/lib.es5.d.ts

/**
 * Obtain the parameters of a function type in a tuple
 */
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any
  ? P : never;
1
2
3
4
5
6
7

示例:

type A = Parameters<() =>void>; // []
type B = Parameters<typeofArray.isArray>; // [any]
type C = Parameters<typeofparseInt>; // [string, (number | undefined)?]
type D = Parameters<typeofMath.max>; // number[]
1
2
3
4

# 12. InstanceType

InstanceType 的作用是获取构造函数类型的实例类型。

定义:

// node_modules/typescript/lib/lib.es5.d.ts

/**
 * Obtain the return type of a constructor function type
 */
type InstanceType<T extendsnew (...args: any) => any> = T extendsnew (...args: any) => infer R ? R : any;
1
2
3
4
5
6

示例:

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
1
2
3
4
5
6
7
8
9
10

# 13. ThisType

ThisType<T> 的作用是用于指定上下文对象的类型。

定义:

// node_modules/typescript/lib/lib.es5.d.ts

/**
 * Marker for contextual 'this' type
 */
interface ThisType<T> { }
1
2
3
4
5
6

注意:使用 ThisType<T> 时,必须确保 --noImplicitThis 标志设置为 true。

示例:

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

const obj: ThisType<Person> = {
  dosth() {
    this.name // string
  }
}
1
2
3
4
5
6
7
8
9
10

# 14. ConstructorParameters

ConstructorParameters<T> 的作用是提取构造函数类型的所有参数类型。它会生成具有所有参数类型的元组类型(如果 T 不是函数,则返回的是 never 类型)。

定义:

// node_modules/typescript/lib/lib.es5.d.ts

/**
 * Obtain the parameters of a constructor function type in a tuple
 */
type ConstructorParameters<T extendsnew (...args: any) => any> = T extendsnew (...args: infer P) => any ? P : never;
1
2
3
4
5
6

示例:

type A = ConstructorParameters<ErrorConstructor>; // [(string | undefined)?]
type B = ConstructorParameters<FunctionConstructor>; // string[]
type C = ConstructorParameters<RegExpConstructor>; // [string, (string | undefined)?]
1
2
3