构建 Typescript 知识体系(九)-高级类型之映射类型

这是我参与更文挑战的第十五天,活动详情查看:更文挑战

通过映射类型,可以从一个旧的类型,生成一个新的类型,比如

把一个类型/接口中的所有属性变为只读

interface Obj {
  a: string;
  b: number;
  c: boolean;
}
/*
类型推断为
type ReadonlyObj = {
    readonly a: string;
    readonly b: number;
    readonly c: boolean;
}
*/
type ReadonlyObj = Readonly<Obj>;
复制代码

Readonly源码实现原理

/**
 * Make all properties in T readonly
 */
type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};
复制代码

Readonly是一个可索引类型的泛型接口,

索引签名是 P in keyof T

T是索引类型的查询操作符,表示类型 T 所有属性的联合类型,

P in 相当于执行了一次 for in 操作, 会把变量 P 依次绑定到T的属性上,

索引签名的返回值 是一个索引访问操作符- T[P],代表属性 P 所指定的类型

最后加上 readonly 就把所有属性变成了只读

把一个类型/接口中的所有属性变为可选

interface Obj {
  a: string;
  b: number;
  c: boolean;
}
/*
类型推断为
type PartialObj = {
    a?: string | undefined;
    b?: number | undefined;
    c?: boolean | undefined;
}
*/
type PartialObj = Partial<Obj>;
复制代码

Partial 源码实现原理

/**
 * Make all properties in T optional
 */
type Partial<T> = {
  [P in keyof T]?: T[P];
};
复制代码

抽取一个类型/接口中的一些子集

interface Obj {
  a: string;
  b: number;
  c: boolean;
}
/*
类型推断为
type PickObj = {
    a: string;
    b: number;
}
*/
type PickObj = Pick<Obj, "a" | "b">;
复制代码

Pick<T, K extends keyof T> 源码实现原理

/**
 * 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];
};
复制代码

T代表要抽取的对象

K有一个约束: 一定是来自T所有属性字面量的联合类型

新的类型/属性一定要从K中选取,

总结

以上三种 官方称为 同态, 只会作用于指定的属性(如上面的 Obj),而不会引入新的属性,

创建一些新的属性

interface Obj {
  a: string;
  b: number;
  c: boolean;
}

/*
 类型推断为
 type RecordObj = {
    x: Obj;
    y: Obj;
}
 */
type RecordObj = Record<"x" | "y", Obj>;
复制代码

RecordObj 是一个非 同态的类型,

总结

映射类型本质上是一个预先定义的泛型接口,通常还会结合索引类型获取对象的属性和属性值,从而将一个对象映射成我们想要的结构。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享