TypeScript/TS入门学习6

95 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情

映射类型

  • 当你不想重复定义类型,一个类型可以以另一个类型为基础创建新类型,通俗的话就是,以一个类型为基础,根据它推断出新的类型
  • Readonly / Partial 关键字
  • Record / Pick 映射关系
  • Readonly Partial 和 Pick 是同态的,但 Record 不是,因为Record并不需要输入类型来拷贝属性,所以它不属于同态

readonly 只读映射

定义一个IPerson接口,然后定义一个MyReadonly类型,接收一个类型,最终类型是这个接收的类型的所有属性都是readonly的属性;

interface IPerson {
    name: string;
    age: number;
}
// {
//   readonly  name: string;
//   readonly  age: number;
// }
type MyReadonly<T> = {
    readonly [P in keyof T]: T[P]
}
type res = MyReadonly<IPerson>

Partial可选映射

同readonly一样,直接将 源类型映射成所有属性为可选的类型。

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

type res=MyPartial<IPerson>

image.png

可以通过 + - 添加或者删除

这个例子直接把readonly 和 可选干掉了

interface IPerson {
    readonly name?: string;
    readonly age?: number;
}
type Test<T> = {
    -readonly [K in keyof T]-?: T[K];
}

type res = Test<IPerson>

内置的Readonly / Partial

interface IPerson3 {
    name: string;
    age: number;
}
type res1 = Readonly<IPerson3>
type res2 = Partial<IPerson3>


Record 指作为一个单位来处理的一组相连的数据 映射类型

将第一个联合类型所有可能的类型都作为新类型的属性,属性值的类型为第二个参数的类型. 想要做为属性的就写在前面,想要做为值的类型写在后面

type Name = "person" | "animal"
type Person = {
    name: string;
    age: number;
}
type Type1 = Record<Name, Person>


type MyRecord<T extends string | number | symbol, U> = {
    [P in T]: U;
}

image.png

Pick 将原有类型中的部分类型映射到新类型中

想要映射哪个属性,第二个类型就包含哪个属性

interface IInfo {
    name: string;
    age: number;
}
// 源码
type MyPick<T, P extends keyof T> = {
    [K in P]: T[K];
}
type Type1 = Pick<IInfo, 'name'>

Record不属于同态,我个人理解,是因为它不需要一个具体的复杂类型就可以生成一个类型,也就是可以通过string,number等基础类型生成{x:string:number}类型

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

type MyRecord<T extends string | number | symbol, U> = {
    [P in T]: U;
}

type res = Record<string, number>