很多项目引入TypeScript后只停留在写interface和用any兜底,类型系统的表达能力没有发挥出来。工具类型和条件类型用好了,API响应、表单状态这类重复模式可以收敛成一处定义,字段调整时编译器直接指出所有需要改动的位置。按内置工具类型、条件类型、业务建模三个层次展开。
内置工具类型组合:从基础模型衍生新类型
interface User {
id: number
name: string
email: string
password: string
createdAt: Date
}
// 对外展示视图:剔除敏感字段
type PublicUser = Omit
// 编辑表单:部分字段可选
type UserUpdateInput = Partial>
// 创建入参:去掉服务端生成的字段
type CreateUserInput = Omit
// 按字段类型映射:批量生成校验函数签名
type UserValidators = {
[K in keyof User]: (value: User[K]) => boolean
}
基础模型变更时,衍生类型自动跟着变,不需要同步维护多份定义。
条件类型与infer:类型层面的逻辑推导
// 提取Promise的返回类型
type Unwrap = T extends Promise ? U : T
type R = Unwrap> // string
// 提取数组元素类型
type ElementOf = T extends (infer E)[] ? E : never
type Item = ElementOf // string
// 提取函数参数元组
type ParamsOf = T extends (...args: infer P) => any ? P : never
// 从接口包装中解出data类型
type ApiResponse = { code: number; data: T; message: string }
type DataOf = T extends ApiResponse ? D : never
条件类型配合泛型约束,可以让请求封装自动推导返回值类型,调用处不需要手动标注:
declare function request(url: string): Promise>;
const res = await request(".../orders/1");
// res.data 自动推导为 Order
API响应统一建模:分页与列表泛型
interface PageResult {
list: T[]
total: number
page: number
pageSize: number
}
type OrderPage = PageResult<{
orderId: string
amount: number
status: "paid" | "pending" | "closed"
}>
// 状态字段收窄为字面量联合,switch分支自动穷尽检查
function renderStatus(s: OrderPage["list"][number]["status"]) {
switch (s) {
case "paid": return "已支付"
case "pending": return "待支付"
case "closed": return "已关闭"
default: {
const _exhaustive: never = s
return _exhaustive
}
}
}
default分支的never赋值是穷尽检查技巧:后端新增状态值时如果漏了case,编译直接报错,比运行时发现少处理一种状态要早得多。
判别联合类型:状态机的类型安全表达
type RequestState =
| { status: "idle" }
| { status: "loading" }
| { status: "success"; data: T }
| { status: "error"; message: string }
function handle(state: RequestState) {
if (state.status === "success") {
console.log(state.data.list) // 只有success分支能访问data
}
}
判别联合比”data可能为null”加一堆可选标记的类型安全得多,每个状态下可用的属性被精确约束。
类型复杂度的边界:可读性优先
三层以上的嵌套条件类型会明显降低团队协作效率,类型体操的价值在于减少运行时错误,不是炫技。判断标准:这个类型省掉的运行时判断和维护成本,是否大于读懂它的成本。业务代码优先组合内置工具类型表达,条件类型保留给请求封装、状态机这类真正的通用抽象,其余场景写简单类型加注释更划算。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/typescript-gong-ju-lei-xing-shi-zhan-tiao-jian-lei-xing-yu/