全国协议5人面授小班,企业级独立开发考核,转业者的IT软件工程师基地 登录/注册 | 如何报名
当前位置: 前端开发   >  TypeScript 映射类型
admin · 更新于 2021-08-06

1. 解释

映射类型可以将已知类型的每个属性都变为可选的或者只读的。

2. Readonly 与 Partial 关键字

先来看这样一个任务:将 Person 接口的每个属性都变为可选属性或者只读属性。

interface Person{
  name: string
  age: number}type PersonOptional = Partial<Person>type PersonReadonly = Readonly<Person>
代码块
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

代码解释:

第 6 行,通过 Partial<Person> 这样的语法格式得到类型别名 PersonOptional,等价于:

type PersonOptional = {
  name?: string
  age?: number}
代码块
  • 1
  • 2
  • 3
  • 4

第 7 行,通过 Readonly<Person> 这样的语法格式得到类型别名 PersonReadonly,等价于:

type PersonReadonly = {
  readonly name: string
  readonly age: number}
代码块
  • 1
  • 2
  • 3
  • 4

3. 两个关键字的源码分析

来看它们的实现源码:

type Readonly<T> = {
  readonly [K in keyof T]: T[K]}type Partial<T> = {
  [K in keyof T]?: T[K]}
代码块
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

源码就使用了映射类型的语法 [K in Keys],来看这个语法的两个部分:

  1. 类型变量 K:它会依次绑定到每个属性,对应每个属性名的类型。
  2. 字符串字面量构成的联合类型的 Keys:它包含了要迭代的属性名的集合。

我们可以使用 for...in 来理解,它可以遍历目标对象的属性。

接下来继续分析:

  • Keys,可以通过 keyof 关键字取得,假设传入的类型是泛型 T,得到 keyof T,即为字符串字面量构成的联合类型("name" | "age")。
  • [K in keyof T],将属性名一一映射出来。
  • T[K],得到属性值的类型。

已知了这些信息,我们就得到了将一个对象所有属性变为可选属性的方法:

[K in keyof T]?: T[K]
代码块
  • 1

进而可得:

type Partial<T> = {
  [K in keyof T]?: T[K]}
代码块
  • 1
  • 2
  • 3

Readonly<T> 和 Partial<T> 都有着广泛的用途,因此它们与 Pick 一同被包含进了 TypeScript 的标准库里:

type Pick<T, K extends keyof T> = {
  [P in K]: T[P]}interface User {
  id: number
  age: number
  name: string}type PickUser = Pick<User, 'id'>
代码块
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

代码解释:

最后一行,就相当于 type PickUser = { id: number }

4. 小结

映射类型的语法是 [K in Keys],比较简单,但是由此我们分析了几个 TypeScript 标准库中好用的工具类型。TypeScript 中工具类型有很多,感兴趣的同学可以深入了解一下。


为什么选择汉码未来