技术
·
阅读 7 分钟
TypeScript 类型体操入门
TypeScript 的类型系统远比你想象的强大。本文从基础泛型出发,逐步介绍条件类型、映射类型和模板字面量类型,带你领略类型编程的魅力。
为什么要学类型体操?
TypeScript 的类型系统是图灵完备的,这意味着它可以进行复杂的类型计算。掌握高级类型技巧,可以帮助你写出更安全、更灵活的代码,让编译器成为你最好的搭档。
泛型基础
泛型是类型编程的基石。它让函数和类型可以接受类型参数:
// 基础泛型函数
function identity<T>(value: T): T {
return value;
}
// 泛型约束
function getLength<T extends { length: number }>(value: T): number {
return value.length;
}
getLength("hello"); // ✅
getLength([1, 2, 3]); // ✅
getLength(123); // ❌ 数字没有 length 属性
条件类型
条件类型类似于三元表达式,但作用于类型层面:
type IsString<T> = T extends string ? "yes" : "no";
type A = IsString<string>; // "yes"
type B = IsString<number>; // "no"
// 实用案例:提取 Promise 内部类型
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
type C = UnwrapPromise<Promise<string>>; // string
type D = UnwrapPromise<number>; // number
映射类型
映射类型可以基于已有类型生成新类型:
// 将所有属性变为可选
type MyPartial<T> = {
[K in keyof T]?: T[K];
};
// 将所有属性变为只读
type MyReadonly<T> = {
readonly [K in keyof T]: T[K];
};
// 实际使用
interface User {
name: string;
age: number;
email: string;
}
type PartialUser = MyPartial<User>;
// { name?: string; age?: number; email?: string; }
模板字面量类型
TypeScript 4.1 引入的模板字面量类型,可以对字符串类型进行模式匹配和组合:
type EventName = `on${Capitalize<'click' | 'focus' | 'blur'>}`;
// "onClick" | "onFocus" | "onBlur"
// 更复杂的例子:生成 getter 名称
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
type UserGetters = Getters<User>;
// { getName: () => string; getAge: () => number; getEmail: () => string; }
实战练习
推荐几个练习类型体操的资源:
- Type Challenges — GitHub 上的开源题库,从简单到地狱难度
- TypeScript Playground — 在线练习环境,即时看到类型推导结果
- TypeScript 官方文档 — Handbook 中的高级类型章节
总结
类型体操不是炫技,而是为了写出更健壮的代码。从日常开发中的简单泛型开始,逐步尝试更复杂的类型编程,你会发现 TypeScript 的类型系统是一个充满乐趣的世界。