TypeScript 类型体操:让代码更安全
TypeScript 的类型系统是图灵完备的。本文分享 5 个让代码更健壮的类型技巧。
TypeScript 类型体操:让代码更安全
TypeScript 不只是给 JavaScript 加类型。它的类型系统是图灵完备的,可以做很多强大的事情。
一、用 satisfies 保证类型安全
// ❌ 容易丢失字面量类型
const config: Config = {
api: '/users',
timeout: 5000,
};
config.api; // 类型是 string,不是字面量 '/users'
// ✅ 保留字面量类型,同时校验结构
const config = {
api: '/users',
timeout: 5000,
} satisfies Config;
config.api; // 类型是 '/users'
二、用 as const 锁定常量
const STATUS = {
PENDING: 'pending',
SUCCESS: 'success',
ERROR: 'error',
} as const;
// 类型是 'pending' | 'success' | 'error',而不是 string
type Status = typeof STATUS[keyof typeof STATUS];
三、用模板字面量类型生成路径
type ApiPaths =
| '/users'
| '/users/:id'
| '/posts'
| '/posts/:id';
// 自动生成所有路径
type ExtractParams<T extends string> =
T extends `${string}:${infer P}` ? P : never;
type ParamsOf<T extends string> =
T extends `${string}:${infer P}/${infer Rest}`
? P | ParamsOf<Rest>
: T extends `${string}:${infer P}`
? P
: never;
type UserParams = ParamsOf<'/users/:id/posts/:postId'>;
// type UserParams = 'id' | 'postId'
四、用 Zod 在运行时校验
import { z } from 'zod';
const UserSchema = z.object({
id: z.string().uuid(),
name: z.string().min(1),
email: z.string().email(),
age: z.number().int().positive().optional(),
});
type User = z.infer<typeof UserSchema>;
function createUser(data: unknown): User {
return UserSchema.parse(data); // 运行时校验 + 类型推导
}
五、用类型守卫收窄类型
interface Circle {
kind: 'circle';
radius: number;
}
interface Square {
kind: 'square';
sideLength: number;
}
type Shape = Circle | Square;
function area(shape: Shape): number {
switch (shape.kind) {
case 'circle':
return Math.PI * shape.radius ** 2;
case 'square':
return shape.sideLength ** 2;
}
}
六、用 Pick/Omit 派生类型
interface User {
id: string;
name: string;
email: string;
password: string;
createdAt: Date;
}
// 不包含敏感字段的公开类型
type PublicUser = Omit<User, 'password'>;
// 创建用户时的输入类型
type CreateUserInput = Pick<User, 'name' | 'email'> & {
password: string;
};
七、用 Record 构造映射类型
type Role = 'admin' | 'user' | 'guest';
type Permissions = Record<Role, string[]>;
// 类型为:
// {
// admin: string[];
// user: string[];
// guest: string[];
// }
const perms: Permissions = {
admin: ['read', 'write', 'delete'],
user: ['read', 'write'],
guest: ['read'],
};
写在最后
好的类型设计能让代码自我解释。
类型不是束缚,而是文档。
当你的类型设计得当时,IDE 能给你精确的提示,重构也变得更安全。这才是 TypeScript 的真正威力。
希望这些技巧对你有帮助! 🎯
回到首页感谢阅读 · 欢迎在下方留言