高级类型
mapped、conditional、literal、template literal、recursive。
35 分钟
高级类型
映射类型、条件类型、字面量类型、模板字面量类型与递归类型是 TypeScript 类型系统的「元编程」层。本课深入这些机制,帮你读懂 nestjs-essentials 与 nextjs-essentials 依赖库中的复杂泛型,并在 typescript-essentials 泛型基础上构建可复用的类型工具。
学习目标
- 编写 mapped type 批量变换对象属性
- 使用 conditional type 与 infer 提取类型
- 用 template literal type 生成字符串联合
映射类型 Mapped Types
type Optional<T> = {
[K in keyof T]?: T[K];
};
type Nullable<T> = {
[K in keyof T]: T[K] | null;
};
type ReadonlyDeep<T> = {
readonly [K in keyof T]: T[K] extends object ? ReadonlyDeep<T[K]> : T[K];
};
interface User {
id: number;
profile: { name: string };
}
type PartialUser = Optional<User>;
条件类型 Conditional Types
type IsArray<T> = T extends unknown[] ? true : false;
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
type ApiResult<T> = T extends { data: infer D } ? D : never;
async function load(): Promise<{ data: Lesson[] }> {
return { data: [] };
}
type Lessons = UnwrapPromise<ReturnType<typeof load>>; // { data: Lesson[] }
type LessonList = ApiResult<Awaited<ReturnType<typeof load>>>; // Lesson[]
模板字面量类型
type HttpMethod = "GET" | "POST" | "PATCH" | "DELETE";
type ApiPath = `/api/${string}`;
type RouteKey = `${HttpMethod} ${ApiPath}`;
const routes: Record<RouteKey, () => void> = {
"GET /api/tracks": () => {},
"POST /api/lessons": () => {},
};
// 事件名模式
type EventName = `on${Capitalize<string>}`;
递归类型
type JsonValue =
| string
| number
| boolean
| null
| JsonValue[]
| { [key: string]: JsonValue };
type DeepPartial<T> = {
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};
分布式条件类型
type ToArray<T> = T extends unknown ? T[] : never;
type StrOrNumArray = ToArray<string | number>; // string[] | number[]
type NonNullableFields<T> = {
[K in keyof T]: NonNullable<T[K]>;
};
练习
- 实现
Mutable<T>移除 readonly