共计 2759 个字符,预计需要花费 7 分钟才能阅读完成。
- 阐明 :目前网上没有 TypeScript 最新官网文档的中文翻译,所以有了这么一个翻译打算。因为我也是 TypeScript 的初学者,所以无奈保障翻译百分之百精确,若有谬误,欢送评论区指出;
- 翻译内容 :暂定翻译内容为 TypeScript Handbook,后续有空会补充翻译文档的其它局部;
- 我的项目地址 :TypeScript-Doc-Zh,如果对你有帮忙,能够点一个 star ~
本章节官网文档地址:Mapped Types
映射类型
有时候咱们不想反复编写代码,这时候就须要基于某个类型创立出另一个类型。
索引签名用于为那些没有提前申明的属性去申明类型,而映射类型是基于索引签名的语法构建的。
type OnlyBoolsAndHorses = {[key: string]: boolean | Horse; | |
}; | |
const conforms: OnlyBoolsAndHorses = { | |
del: true, | |
rodney: false, | |
}; |
映射类型也是一种泛型类型,它应用 PropertyKey
(属性键)的联结类型(通常通过 keyof 创立)去遍历所有的键,从而创立一个新的类型:
type OptionsFlags<Type> = {[Property in keyof Type]: boolean; | |
}; |
在这个例子中,OptionsFlags
会承受类型 Type
的所有属性,并将它们的值改为布尔值。
type FeatureFlags = {darkMode: () => void; | |
newUserProfile: () => void;}; | |
type FeatureOptions = OptionsFlags<FeatureFlags>; | |
^ | |
/* | |
type FeatureOptions = { | |
darkMode: boolean; | |
newUserProfile: boolean; | |
} | |
*/ |
映射修饰符
在映射的时候还有两个附加的修饰符可供使用,也就是 readonly
和 ?
,它们别离用于申明属性的只读性和可选性。
要移除或者增加修饰符,只须要给修饰符增加前缀 -
或者 +
即可。如果没有增加前缀,则默认应用 +
。
// 移除类型中属性的只读性 | |
type CreateMutable<Type> = {-readonly [Property in keyof Type]: Type[Property]; | |
}; | |
type LockedAccount = { | |
readonly id: string; | |
readonly name: string; | |
}; | |
type UnlockedAccount = CreateMutable<LockedAccount>; | |
^ | |
/* | |
type UnlockedAccount = { | |
id: string; | |
name: string; | |
} | |
*/ |
// 移除类型中属性的可选性 | |
type Concrete<Type> = {[Property in keyof Type]-?: Type[Property]; | |
} | |
type MaybeUser = { | |
id: string; | |
name?: string; | |
age?: number; | |
}; | |
type User = Concrete<MaybeUser>; | |
^ | |
/* | |
type User = { | |
id: string; | |
name: string; | |
age: number; | |
} | |
*/ |
通过 as
实现键的从新映射
在 TypeScript4.1 或者更高的版本中,你能够在映射类型中应用 as
子句实现键的从新映射:
type MappedTypeWithNewProperties<Type> = {[Properties in keyof Type as NewKeyType]: Type[Properties] | |
} |
你能够应用诸如模板字面量类型这样的个性从原来的属性名中去创立新的属性名:
type Getters<Type> = {[Property in keyof Type as `get${Capitalize<string & Property>}`]: () => Type[Property] | |
}; | |
interface Person { | |
name: string; | |
age: number; | |
location: string; | |
} | |
type LazyPerson = Getters<Person>; | |
^ | |
/* | |
type LazyPerson = {getName: () => string; | |
getAge: () => number; | |
getLocation: () => string;} | |
*/ |
你能够通过条件类型产生 never
类型,从而过滤掉某些键:
// 移除 kind 属性 | |
type Exclude<T,U> = T extends U ? never : T | |
type RemoveKindField<Type> = {[Property in keyof Type as Exclude<Property,'kind'>]: Type[Property] | |
}; | |
interface Circle { | |
kind: 'circle'; | |
radius: number; | |
} | |
type KindlessCircle = RemoveKindField<Circle>; | |
^ | |
/* | |
type KindlessCircle = {radius: number;} | |
*/ |
不仅仅是 string | number | symbol
这样的联结类型,任意的联结类型都能够映射:
type EventConfig<Events extends {kind: string}> = {[E in Events as E['kind']]: (event: E) => void; | |
} | |
type SqureEvent = {kind: 'squre', x: number, y: number}; | |
type CircleEvent = {kind: 'circle', radius: number}; | |
type Config = EventConfig<SqureEvent | CricleEvent> | |
/** | |
type Config = {squre: (event: SqureEvent) => void; | |
circle: (event: CircleEvent) => void; | |
} | |
/ |
映射类型的进一步利用
映射类型也能够和本章(类型操控)介绍的其它个性搭配应用。举个例子,上面是一个应用了条件类型的映射类型,依据对象是否有一个设置为字面量 true
的属性 pii
,它会返回 true
或者 false
:
type ExtractPII<Type> = {[Property in keyof Type]: Type[Property] extends {pii: true} ? true : false | |
}; | |
type DBFileds = {id: { format: 'incrementing'}; | |
name: {type: string; pii: true}; | |
}; | |
type ObjectsNeedingGDPRDeletion = ExtractPII<DBFileds>; | |
^ | |
/* | |
type ObjectsNeedingGDPRDeletion = { | |
id: false; | |
name: true; | |
} | |
*/ |
正文完