引言:为什么TypeScript是现代开发者的必备技能
TypeScript已牢固地成为企业级开发的事实标准。根据Stack Overflow的调查,超过70%的前端开发者正在使用或计划使用TypeScript。在面试中,关于这项技术的问题必不可少——即使职位正式标注为“JavaScript开发者”。
在本文中,我们将解析技术面试中必定会问到的关键主题:从基础类型到复杂泛型和条件类型。内容按照“由浅入深”的原则组织,以便您能够系统地准备。
1. 基础:类型、接口及其区别
1.1. 原始类型和特殊类型
我们从基础开始。面试官几乎肯定会问到any、unknown、never和void。
any— 关闭类型检查。仅在迁移时作为最后手段使用。unknown— any的安全替代方案。使用前需要进行类型检查。never— 永远不会发生的类型(抛出异常的函数或无限循环)。void— 函数没有返回值。
function throwError(msg: string): never { throw new Error(msg);}
function log(msg: string): void { console.log(msg);}
let data: unknown = JSON.parse('{"name":"John"}');// data.name // 错误!需要检查if (typeof data === 'object' && data !== null) { console.log((data as Record<string, unknown>).name);}1.2. Interface vs Type:如何选择?
这是一个经典问题。两种方法都可以描述对象的结构,但存在细微差别:
- Interface — 可扩展(
extends),可合并(declaration merging)。 - Type — 可以描述联合类型、交叉类型、原始类型。不支持声明合并。
// Interface - 扩展interface User { name: string;}interface User { age: number; // declaration merging}const user: User = { name: 'Alice', age: 30 };
// Type - 联合type Status = 'active' | 'inactive';type UserOrStatus = User | Status;建议: 对于对象和类,使用interface;对于复杂组合,使用type。
2. 泛型和工具类型
2.1. 泛型:通用编程
任何严肃的面试都离不开泛型。能够编写适应传入参数的类型,是开发者成熟度的标志。
// 简单泛型function identity<T>(arg: T): T { return arg;}
// 泛型约束function getLength<T extends { length: number }>(arg: T): number { return arg.length;}
// 数组泛型function last<T>(arr: T[]): T | undefined { return arr[arr.length - 1];}经常会被问到infer——用于在条件类型中推断类型的关键字:
// 从Promise中提取元素类型type Unwrap<T> = T extends Promise<infer U> ? U : T;type Result = Unwrap<Promise<number>>; // number2.2. 工具类型(Utility Types)
了解内置工具是必备基础。面试官可能会要求手动实现一个类似功能。
Partial<T>— 所有字段变为可选。Required<T>— 所有字段变为必选。Pick<T, K>— 仅选择指定的键。Omit<T, K>— 排除指定的键。