TypeScript 类型体操实战:5 个高级类型编程技巧
TypeScript 的强大之处不仅在于静态类型检查,更在于它的类型系统可以像编程语言一样灵活。许多开发者熟悉基础类型,但在面对复杂场景时,仍然束手无策,最终选择 any 或 as 暴力破解。
今天,我将分享 5 个 TypeScript 高级类型编程技巧,帮助你写出更健壮、更智能的类型定义。这些技巧来自真实项目经验,涵盖 API 响应处理、表单校验、路由配置等场景。
1. 动态表单校验:用 Mapped Types 实现类型安全校验
假设我们有一个表单对象:
type UserForm = {
name: string;
age: number;
email: string;
};
我们希望为每个字段定义一个校验函数,返回错误信息或 undefined。利用 Mapped Types,可以动态生成校验类型:
type Validator<T> = {
[K in keyof T]: (value: T[K]) => string | undefined;
};
const userValidators: Validator<UserForm> = {
name: (value) => (value.length > 3 ? undefined : "Name too short"),
age: (value) => (value >= 18 ? undefined : "Must be adult"),
email: (value) => (value.includes("@") ? undefined : "Invalid email"),
};
优势:
✅ 自动关联字段类型,避免手写重复代码
✅ 编辑器智能提示,防止拼写错误
2. API 响应类型:用 Union Types 处理成功/失败场景
后端 API 通常返回两种可能:成功(data)或失败(error)。我们可以用 Union Types 精确描述:
type ApiResponse<T> =
| { status: "success"; data: T }
| { status: "error"; message: string };
async function fetchUser(): Promise<ApiResponse<User>> {
const res = await fetch("/api/user");
const data = await res.json();
return data;
}
// 使用时,TypeScript 会自动推断可能的类型
const result = await fetchUser();
if (result.status === "success") {
console.log(result.data); // ✅ 类型安全
} else {
console.error(result.message); // ✅ 类型安全
}
优势:
✅ 强制处理所有可能的返回情况,避免运行时错误
3. 递归类型:处理嵌套路由配置
在 React/Vue 路由配置中,嵌套路由很常见。我们可以用 递归类型 描述无限层级的路由结构:
type Route = {
path: string;
children?: Route[];
};
const routes: Route[] = [
{
path: "/dashboard",
children: [
{ path: "profile" },
{ path: "settings", children: [{ path: "security" }] },
],
},
];
进阶版:结合 template literal types 自动生成完整路径:
type JoinPath<Parent extends string, Child extends string> =
`${Parent}/${Child}`;
type FullPath<Route extends { path: string; children?: any[] }> =
Route["children"] extends infer Children
? Children extends any[]
? JoinPath<Route["path"], FullPath<Children[number]>>
: Route["path"]
: Route["path"];
优势:
✅ 自动推断嵌套路由路径,减少手动拼接错误
4. 条件类型:实现 RBAC 权限控制
假设我们有用户角色 Admin 和 User,不同角色能访问的页面不同:
type Role = "admin" | "user";
type AllowedPages<Role> =
Role extends "admin" ? "dashboard" | "settings" | "users"
: Role extends "user" ? "dashboard" | "profile"
: never;
function navigate<Role>(role: Role, page: AllowedPages<Role>) {
// ...
}
navigate("admin", "users"); // ✅
navigate("user", "users"); // ❌ 类型错误
优势:
✅ 在编译时阻止非法访问,避免运行时权限漏洞
5. 模板字面量类型:自动生成 CSS 类名
在组件库开发中,我们经常需要动态生成 BEM 风格的类名(如 button--primary)。利用 模板字面量类型,可以做到类型安全:
type BEM<Block extends string, Element extends string, Modifier extends string> =
`${Block}__${Element}--${Modifier}`;
type ButtonClass = BEM<"button", "text", "primary">; // "button__text--primary"
实战扩展:结合 keyof 动态生成所有可能的组合:
type Modifiers = "primary" | "danger" | "disabled";
type AllButtonClasses = `button__${"text" | "icon"}--${Modifiers}`;
// 生成: "button__text--primary" | "button__text--danger" | ...
优势:
✅ 避免手写字符串,减少拼写错误
总结:如何系统学习 TypeScript 类型编程?
-
基础必备:掌握
extends、infer、keyof、Mapped Types -
阅读源码:学习 Vue/React/Redux 的类型定义
-
性能优化:避免深层递归,必要时用
// @ts-ignore临时绕过
讨论:你在项目中用过哪些高级类型技巧?欢迎在评论区分享! 🚀