TypeScript学习(六):Handbook -> Keyof Type Operator & Mapped Types

288 阅读2分钟

上篇文章中简单介绍了 keyof 操作符

下方 Keyof 的返回的类型似于 “x” | "y"

type Point = {x: number; y: number}
type P = Keyof Point

索引签名

类型中有索引签名的时候,Keyof返回的是 number 类型

type Arrayish = { [n: number]: unknow }
// number
type A = Keyof Arrayish

有一个特殊现象,由于 JS 中对象的key都会被转化为 string,因此当指定 key 为 string的时候有如下表现

type Mapish = { [k: string]: boolean }
// string | number
type M = Keyof Mapish;

Mapped Types

Mapped Types 是建立在对象索引签名的格式上,被用来声明一个未在第一时间声明的对象属性。通常使用 Keyof 操作符

type OptionsFlags<T> = {
    [P in Keyof T]: boolean
}

利用 Mapped Types 实现 Partical

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

Mapping Modifiers

利用 - readonly 移除属性的只读限制,利用-?移除属性的可选限制

type CreateMutable<T> = {
    -readonly [P in Keyof T]: T[P]
}
type LockedAccount = {
    readonly id:string;
    readonly name:string;
}
type UnlockAccount = CreateMutable<LockedAccount>

type Concrete<T> = {
    [P in keyof T]-?: T[P]
}
type  MaybeUser = {
    id: string;
    name?: string;
    age?: number;
}
type User = Concrete<MaybeUser>

as

TS 4.1 新特性,可以使用 as 重新命名 properties

下方,结合字面量使用

Capitalize是将首字母大写,其泛型类型受限为string。但是,Property 可能是 number、string、symbol之一。一次不符合条件,所以使用 string & Property 对类型进行限制。

type Getters<T> = {
    [P in Keyof T as `get${Capitalize<string & Property>}`]: () => T[P]
}

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

// getName:() => string 
// etc.
type LazyPerson = Getters<Person>

拓展 ---> type的 & 操作

注意:两个interface & 操作的时候,对于共同的属性,会把每个属性都进行 & 操作;对于多余的属性,直接添加即可。

// a 的类型为 'string'
type a = string & 'test'

// c 的类型为 string
type b = string | number | symbol
type c = b & string

// d 的类型为 never
type d = string & number


// 两个interface 操作
interface e {
    a: number
}

interface f {
    a: string
    d: number
}

// e的类型为 a:never d:number
type e = e & f