Appearance
映射类型
通过映射类型
,可以从一个旧的类型,生成一个新的类型,比如
只读 readonly
把一个类型 / 接口中的所有属性变为
typescript
interface Obj {
a: string;
b: number;
c: boolean;
}
/*
类型推断为
type ReadonlyObj = {
readonly a: string;
readonly b: number;
readonly c: boolean;
}
*/
type ReadonlyObj = Readonly<Obj>;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
Readonly 源码实现原理
typescript
/**
* Make all properties in T readonly
*/
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
1
2
3
4
5
6
2
3
4
5
6
Readonly
是一个可索引类型的泛型接口, 索引签名是 P in keyof T
, T
是索引类型的查询操作符,表示类型 T 所有属性的联合类型, P in
相当于执行了一次 for in
操作, 会把变量 P 依次绑定到 T 的属性上, 索引签名的返回值 是一个索引访问操作符 - T[P]
, 代表属性 P 所指定的类型 最后加上 readonly
就把所有属性变成了只读
可选 Partial
把一个类型 / 接口中的所有属性变为
typescript
interface Obj {
a: string;
b: number;
c: boolean;
}
/*
类型推断为
type PartialObj = {
a?: string | undefined;
b?: number | undefined;
c?: boolean | undefined;
}
*/
type PartialObj = Partial<Obj>;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
Partial 源码实现原理
typescript
/**
* Make all properties in T optional
*/
type Partial<T> = {
[P in keyof T]?: T[P];
};
1
2
3
4
5
6
2
3
4
5
6
必填 Required
typescript
interface Foo {
name: string
age?: number
}
type Bar = Required<Foo>
// 相当于
type Bar = {
name: string
age: string
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
源码
typescript
type Require<T> = {
[p in keyof T]-?: T[P]
}
1
2
3
2
3
抽取 Pick
一个类型 / 接口中的一些子集
typescript
interface Obj {
a: string;
b: number;
c: boolean;
}
/*
类型推断为
type PickObj = {
a: string;
b: number;
}
*/
type PickObj = Pick<Obj, "a" | "b">;
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
Pick 源码实现原理
typescript
/**
* 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
2
3
4
5
6
7
T
代表要抽取的对象
K
有一个约束:一定是来自 T
所有属性字面量的联合类型
新的类型 / 属性一定要从 K
中选取,
以上三种 官方称为 同态, 只会作用于指定的属性(如上面的 Obj),而不会引入新的属性,
Record
Record 的内部定义,接收两个泛型参数;Record 后面的泛型就是对象键和值的类型 一个对象的 key 和 value 类型
Record<string, never> 空对象 Record<string, unknown> 任意对象 {} 任何不为空的对象
typescript
interface PageInfo {
title: string;
}
type Page = "home" | "about" | "contact";
const nav: Record<Page, PageInfo> = {
about: { title: "about" },
contact: { title: "contact" },
home: { title: "home" },
};
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
比如我需要一个对象,有 ABC 三个属性,属性的值必须是数字,那么就这么写:
typescript
type keys = 'A' | 'B' | 'C'
const result: Record<keys, number> = {
A: 1,
B: 2,
C: 3
}
1
2
3
4
5
6
2
3
4
5
6
源码
typescript
type Record<K extends string | number | symbol, T> = {
[P in K]: T;
}
1
2
3
2
3
Exclude
作用:如果 T 是 U 的子类型则返回 never 不是则返回 T
typescript
type A = number | string | boolean
type B = number | boolean
type Foo = Exclude<A, B>
// 相当于
type Foo = string
1
2
3
4
5
6
2
3
4
5
6
源码
typescript
type Exclude<T, U> = T extends U ? never : T
1
Extract
和 Exclude 相反
typescript
type A = number | string | boolean
type B = number | boolean
type Foo = Extract<A, B>
// 相当于
type Foo = number | boolean
1
2
3
4
5
6
2
3
4
5
6
源码
typescript
type Extract<T, U> = T extends U ? T : never
1
Omit
作用:生成一个新类型,该类型拥有 T 中除了 K 属性以外的所有属性
typescript
type Foo = {
name: string
age: number
}
type Bar = Omit<Foo, 'age'>
// 相当于
type Bar = {
name: string
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
源码
typescript
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>
1
NonNullable
从泛型 T 中排除掉 null 和 undefined
typescript
NonNullable<T>
1
源码
typescript
type NonNullable<T> = T extends null | undefined ? never : T;
type t = NonNullable<'name' | undefined | null>;
/* type t = 'name' */
1
2
3
4
2
3
4
Parameters
从函数类型的参数中使用的类型构造元组类型。
typescript
function foo(p1: string, p2: number) {}
type params = Parameters<typeof foo>; // --> type params = [p1: string, p2: number]
1
2
3
2
3
源码
typescript
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
1
2
2
ConstructorParameters
typescript
class A {
private name;
private age;
constructor(name: string, age: number) {
this.age = age;
this.name = name;
}
}
type B = ConstructorParameters<typeof A>;
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
源码
typescript
type ConstructorParameters<T extends abstract new (...args: any) => any> =
T extends abstract new (...args: infer P) => any ? P : never;
1
2
2
限制 string
- Uppercase 约束 小写
- Lowercase 约束 大写
- Capitalize 约束 首字母大写
- Uncapitalize 约束 首字母小写
typescript
const _uppercase: Uppercase<'hello'> = 'HELLO';
const _lowercase: Lowercase<'hello'> = 'hello';
const _capitalize: Capitalize<'hello'> = 'Hello';
const _uncapitalize: Uncapitalize<'Hello'> = 'hello';
1
2
3
4
2
3
4
总结
映射类型本质上是一个预先定义的泛型接口,通常还会结合索引类型获取对象的属性和属性值,从而将一个对象映射成我们想要的结构。