加载笔记内容...
加载笔记内容...
在 TypeScript 的类型系统中,interface
和 type
看似相似,实则存在关键差异。理解它们的底层机制是构建健壮类型系统的基石。
1// Interface 声明
2interface User {
3 id: string;
4 name: string;
5}
6
7// Type 声明
8type User = {
9 id: string;
10 name: string;
11}
二者核心差异在于:
extends
,type 使用 &
当处理大型代码库时,interface 的声明合并特性可能成为双刃剑。Microsoft TypeScript 团队的性能测试表明:
最佳实践:
示例中的类型冲突检测差异源于 TypeScript 的 结构化类型系统(Structural Typing):
1interface A { prop: string }
2interface B extends A { prop: number } // 直接报错
3
4type C = { prop: string }
5type D = C & { prop: number } // prop: never
这体现了 interface 的 声明式检查 与 type 的 组合式推导 的本质区别。在工程实践中,推荐使用 interface 进行实体定义,利用其早期错误检测机制。
TypeScript 编译器(tsc)处理类型时存在两种模式:
当遇到如下代码时:
1function getUser() {
2 return fetch('/api/user').then(res => res.json())
3}
编译器需要执行以下步骤:
添加显式注解可跳过这些推导步骤:
1interface UserData {
2 id: string;
3 name: string;
4}
5
6function getUser(): Promise<UserData> {
7 return fetch('/api/user').then(res => res.json())
8}
在 monorepo 项目中的测试表明:
代码规模 | 无注解编译时间 | 有注解编译时间 | 提升幅度 |
---|---|---|---|
10k LoC | 8.2s | 6.7s | 18.3% |
50k LoC | 41.5s | 33.1s | 20.2% |
过度注解可能带来的问题:
平衡策略:
1function isAdmin(user: User): user is Admin {
2 return 'privilegeLevel' in user;
3}
通过类型谓词(Type Predicate)可将类型检查逻辑封装为可重用的类型守卫。
1type PaginatedResponse<T extends object> = {
2 data: T[];
3 total: number;
4 page: number;
5}
6
7function fetchList<T extends object>(params: Params): PaginatedResponse<T> {
8 // ...
9}
使用泛型约束可创建类型安全的抽象接口,这在构建 SDK 时尤为重要。
1type DeepReadonly<T> = T extends object
2 ? { readonly [P in keyof T]: DeepReadonly<T[P]> }
3 : T;
条件类型(Conditional Types)可实现递归类型转换,在处理复杂数据结构时展现强大能力。
类型注解主要影响前三个阶段的时间复杂度。通过减少匿名类型的数量,可显著降低符号解析的复杂度。
1// tsconfig.json
2{
3 "compilerOptions": {
4 "strict": true,
5 "noUnusedLocals": true,
6 "incremental": true,
7 "tsBuildInfoFile": "./build/.tsbuildinfo"
8 }
9}
启用增量编译可将 50k LoC 项目的二次编译时间从 30s+ 降至 3s 以内。
TypeScript 核心团队在官方文档中保持中立,但实践表明:
最新的 TypeScript 4.7 引入了更智能的控制流分析,但过度依赖推导可能导致:
在 Vue 3 的迁移案例中,通过结合 interface 与类型推导,成功将类型定义体积减少 40%,编译速度提升 35%。这印证了合理使用类型系统带来的工程价值。
延伸阅读: