可选类型不一定符合预期
const doThing = (ctx?: { traceId?: string }) => {}
const doAnotherThing = (ctx: { traceId: string | undefined }) => {}
const mainFunction = (ctx: { traceId?: string }) => {
doThing()
// 必须传入 traceId
doAnotherThing({ traceId: ctx.traceId })
}
模板字符串类型
type SupportedLangs = "en" | "pt"
type FooterIds = "header" | "footer"
type AllLocaleIDs = `${SupportedLangs}_${FooterIds}`
使用 Pick 和 Omit
interface Album {
id: string
title: string
artist: string
releaseYear?: number
genre?: { parentGenre?: string, subGenre?: string }
}
// Pick 挑选
type AlbumData1 = Pick< Album, 'title' | 'artist' >
// Omit 省略
type AlbumData2 = Omit< Album, 'id' | 'releaseYear' | 'genre' >
// extract 提取
// ❌ 不起作用
type AlbumData3 = Extract< Album, 'id' | 'artist' >
// exclude 排除
// 全量返回
type AlbumData4 = Exclude< Album, 'id' | 'artist' >
// ⚠️: 提取和排除只对联合类型起作用
使用 Extract 提取类型
type Example = 'a' | 'b' | 1 | 2 | 8 | 'as'
// extract 提取
type Numbers = Extract<Example, number>
type Strings = Extract<Example, string>
// Exclude 排除
type Numbers2 = Exclude<Example, string>
type Strings2 = Exclude<Example, number>
使用 Exclude 排除类型
// exclude 排除
type AlbumState =
| {
type: 'released'
releaseDate: string
}
| {
type: 'recording'
studio: string
}
| {
type: 'mixing'
engineer: string
}
// exclude 排除
type NotReleased = Exclude< AlbumState, { type: 'released' } >
- 更多内置类型请参考:TypeScript 工具类型
更友好的显示类型
type ComplexType = {
a: string
b: number
} & {
c: boolean
} & {
d: string []
}
type ComplexType2 = {
a: string
b: number
} & Omit<{ c: boolean } & { d: Record<'d', string[]> }, 'c'>
& { e: 'en_US' | 'zh_CN' }
type ShowMe = ComplexType
type ShowMe2 = ComplexType2
export type Prettify<T> = {
[K in keyof T]: T[K]
} & {} // 添加 & {} 避免类型保持为引用形式
type ShowMe3 = Prettify<ComplexType2>
type WithFormProps = { isForm: true, onSubmit: () => void }
type WithoutFormProps = { isForm?: false, onSubmit?: never }
type DialogProps = { open: boolean, onClose: () => void } & (WithFormProps | WithoutFormProps)
type DialogProps_ = Prettify<DialogProps>
在字面量联合类型使用魔法 🧙♀️
type ModelNames =
| 'gtp-4o'
| 'o3-mini'
| 'claude-sonnet-3.7'
| 'gemini-1.5-flash'
| (string & {})
const GTP: ModelNames = 'gtp-4o'
const model: ModelNames = 'qianwen'
// 平替方案
type LooseAutocomplete<T extends string> = T | Omit<string, T>
type Color = LooseAutocomplete<'red' | 'green' | 'blue'>
// ✅ 预设值
const a: Color = 'red'
// ✅ 自定义字符串(例如服务端配置返回的新值)
const b: Color = 'purple'
// ❌ 错误示例:number 不符合 string 类型
// const c: Color = 123
映射类型
type User = {
id: string
name: string
age: number
}
type UserTransfromed = {
// [K in keyof User]: K
// ========= ⬇️ =========
// [K in keyof User]: [K]
// ========= ⬇️ =========
[K in keyof User]: User[K]
}
type UserTransfromed_2 = {
readonly [K in keyof User]?: User[K]
}
type UserTransfromed_3 = {
[K in keyof User as Capitalize<K>]: User[K]
}
type UserTransfromed_4 = {
[K in keyof User as `get${Capitalize<K>}`]: User[K]
}
type UserTransfromed_5 = {
[K in keyof User as `get${Capitalize<K>}`]: () => User[K]
}
type Setters<T extends object> = {
[K in Extract<keyof T, string> as `set${Capitalize<K>}`]?: (value: T[K]) => T[K]
}
// ** 🔄 映射类型 ** -> 动态转换对象类型
type Artist = { name: string; bio: string }
type SubscriberType<T> = {
[Property in keyof T]: (value: T[Property]) => void
}
type ArtistSubscriber = SubscriberType<Artist>
- Capitalize: 转换字符串类型第一个字母为大写。
索引映射类型 (IIMT)
type Prettify<T> = { [K in keyof T]: T[K] } & {} // 添加 & {} 避免类型保持为引用形式
type Actions = {
login: { userName: string, password: string }
logout: { reason: string }
update: { id: string, data: unknown }
}
type ActionAsDiscoUnion = {
// [K in keyof Actions]: { type: K } & Actions[K]
// ========= ⬇️ =========
[K in keyof Actions]: Prettify<{ type: K } & Actions[K]>
}
// 🌰 索引映射类型的基本使用 (📝 从现有值推导类型)
type Values_ = Actions['login']
// type Values_2 = Actions['login' | 'logout' | 'update']
// ========= ⬇️ =========
type Values = Actions[keyof Actions]
type ActionAsDiscoUnion_ = ActionAsDiscoUnion[keyof Actions]
+ - 修饰符
+
-
修饰符可以添加或去掉 readonly
和 ?
,如:
type LockedAccount = { readonly id?: string, readonly name?: string }
// 去除所有属性上的 readonly 和可选修饰符
type CreateMutable<T> = {
-readonly [K in keyof T]-?: T[K]
}
type UnlockedAccount = CreateMutable<LockedAccount>
// 给所有属性添加 readonly 和可选修饰符
type CreateMutableAndReadonly<T> = {
+readonly [K in keyof T]+?: T[K]
}
type FullyMutable = CreateMutableAndReadonly<UnlockedAccount>
通过 as 重新(强制)映射类型
在TypeScript 4.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 EventConfig<Events extends { kind: string }> = {
[E in Events as E["kind"]]: (event: E) => void
}
type SquareEvent = { kind: "square", x: number, y: number }
type CircleEvent = { kind: "circle", radius: number }
type Config = EventConfig<SquareEvent | CircleEvent>
// 使用示例
const _config: Config = {
square: ({ kind, x, y }) => {},
circle: ({ kind, radius }) => {}
}
Last updated on