TypeScript 高级类型技巧
#typescript#types#generics
类型体操入门
TypeScript 的类型系统非常强大,掌握高级类型技巧能让你写出更安全的代码。
条件类型
根据条件推导类型:
// 基础用法
type IsString<T> = T extends string ? true : false;
type A = IsString<'hello'>; // true
type B = IsString<123>; // false
// 分布式条件类型
type ToArray<T> = T extends any ? T[] : never;
type Result = ToArray<string | number>;
// 结果:string[] | number[]
映射类型
基于已有类型创建新类型:
// 只读类型
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
// 可选类型
type Partial<T> = {
[P in keyof T]?: T[P];
};
// 自定义映射
type Nullable<T> = {
[P in keyof T]: T[P] | null;
};
type User = {
name: string;
age: number;
};
type NullableUser = Nullable<User>;
// { name: string | null; age: number | null }
模板字面量类型
利用字符串模板创建类型:
// 基础用法
type Color = 'red' | 'green' | 'blue';
type Size = 'small' | 'medium' | 'large';
type Class = `${Color}-${Size}`;
// 'red-small' | 'red-medium' | 'red-large' | ...
// 实用场景:API 端点
type Method = 'GET' | 'POST' | 'PUT' | 'DELETE';
type Endpoint = `/api/users${'' | `/${string}`}`;
type FullEndpoint = `${Method} ${Endpoint}`;
递归类型
处理嵌套结构:
// 深度只读
type DeepReadonly<T> = {
readonly [P in keyof T]: T[P] extends object
? DeepReadonly<T[P]>
: T[P];
};
// 深度可选
type DeepPartial<T> = T extends object
? { [P in keyof T]?: DeepPartial<T[P]> }
: T;
// 树形结构
type TreeNode = {
name: string;
children?: TreeNode[];
};
工具类型实战
提取 API 响应类型
interface ApiResponse<T> {
code: number;
message: string;
data: T;
}
// 提取 data 类型
type ExtractData<T> = T extends ApiResponse<infer D> ? D : never;
type User = { id: number; name: string };
type UserData = ExtractData<ApiResponse<User>>;
// { id: number; name: string }
构建类型安全的表单
type FormFields<T> = {
[K in keyof T]: {
value: T[K];
error?: string;
touched: boolean;
};
};
type LoginForm = {
username: string;
password: string;
};
type LoginFormState = FormFields<LoginForm>;
类型守卫
运行时类型检查:
// 用户自定义类型守卫
function isString(value: unknown): value is string {
return typeof value === 'string';
}
// 类型保护
function processInput(input: string | number) {
if (typeof input === 'string') {
// 这里 input 被推断为 string
return input.toUpperCase();
}
// 这里 input 被推断为 number
return input.toFixed(2);
}
最佳实践
- 优先使用 interface:用于对象类型定义
- 谨慎使用 any:用 unknown 替代,强制类型检查
- 善用泛型:编写可复用的类型工具
- 类型即文档:好的类型名能说明意图
总结
高级类型技巧能提升代码质量和开发效率,但也要避免过度复杂化。记住:
类型系统是为了帮助开发者,而不是束缚开发者。