TypeScript 高级类型实战:泛型约束、条件类型与模板字面量类型的工业级应用
如果你已经能在项目中使用基本的 TypeScript 类型标注,那么恭喜你——你已经解决了 70% 的类型安全问题。但剩下的 30% 才是 TypeScript 真正强大的地方:通过类型编程在编译期就消除潜在的运行时错误。
泛型约束:让泛型不再”泛”
最简单的泛型可以接受任何类型,但你无法安全地访问参数的任何属性。泛型约束就是为了解决这个问题:
1 | interface HasLength { length: number; } |
实战:约束 Repository 模式
1 | interface Repository<T extends { id: string }> { |
条件类型:类型的 if/else
条件类型让类型能根据条件分支——就像写代码一样写类型:
1 | type IsString<T> = T extends string ? true : false; |
infer 关键字是条件类型的灵魂——它让 TypeScript 在类型推断过程中”捕获”某个类型变量:
1 | // 提取 Promise 的返回值类型 |
模板字面量类型:字符串的类型级操作
TypeScript 4.1 引入了模板字面量类型——你可以像模板字符串一样操作类型:
1 | type EventName<T extends string> = `on${Capitalize<T>}`; |
生产级应用:类型安全的事件系统
1 | type Events = { |
映射类型与工具类型
TypeScript 内置了大量实用工具类型(Utility Types),它们本质上都是映射类型的应用:
| 工具类型 | 作用 | 示例 |
|---|---|---|
Partial<T> |
所有属性变为可选 | Partial<User> |
Required<T> |
所有属性变为必填 | Required<Partial<User>> |
Pick<T, K> |
选取指定属性 | `Pick<User, ‘name’ |
Omit<T, K> |
排除指定属性 | Omit<User, 'id'> |
Record<K, V> |
构造键值对类型 | Record<string, User> |
总结
TypeScript 的类型系统远不止 string、number 这些基础标注。泛型约束让你在保持灵活性的同时不丢失类型安全,条件类型让你能写出”自适应”的类型逻辑,模板字面量类型则打开了字符串类型操作的新世界。把它们组合起来,你能在编译期就消除一整个类别的运行时 Bug——这才是 TypeScript 的核心价值所在。
本文是原创文章,采用CC BY-NC-SA 4.0协议,完整转载请注明来自CC 的技术工坊
