高级TypeScript面试:如何给雇主留下深刻印象
TypeScript早已不仅仅是JavaScript的“超集”。在现代高级职位的面试中,不仅会考察类型知识,还会考察使用条件类型、映射类型、装饰器和类型推断系统的能力。本文将剖析4个关键主题,帮助您自信地通过高级TypeScript技术面试。
1. 条件类型(Conditional Types)与infer关键字
条件类型允许根据条件从两个类型中选择一个。它们基于三元运算符构建:T extends U ? X : Y。面试中可能会要求您编写一个提取函数返回类型的类型。
// 示例:提取函数返回类型type ReturnTypeExtract<T> = T extends (...args: any[]) => infer R ? R : never;
function greet(name: string): string { return "Hello, " + name;}
type GreetReturn = ReturnTypeExtract<typeof greet>; // stringinfer关键字在条件类型内部用于声明一个新的类型变量。它允许从复杂结构中“提取”部分类型。常被问到:“什么是infer,它在哪里使用?”答案是:用于从Promise、函数、元组中提取类型。
// 从Promise中提取元素类型type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
type Result = UnwrapPromise<Promise<number>>; // numbertype Result2 = UnwrapPromise<string>; // string2. 映射类型(Mapped Types)与readonly/optional修饰符
映射类型允许通过遍历现有类型的属性来创建新类型。这是创建Partial<T>或Readonly<T>等工具类型的强大工具。面试中可能会要求实现自己的Pick<T, K>版本。
// 自定义Pick实现type MyPick<T, K extends keyof T> = { [P in K]: T[P];};
interface User { id: number; name: string; email: string;}
type UserBasic = MyPick<User, 'id' | 'name'>;// { id: number; name: string }请注意keyof T——这是一个返回对象键联合类型的运算符。与映射结合使用,可以灵活地转换类型。还常被问到readonly和?(可选)修饰符。可以使用+和-前缀添加或删除它们:
// 从所有属性中删除readonlytype Mutable<T> = { -readonly [P in keyof T]: T[P];};
type ImmutableUser = Readonly<User>;type MutableUser = Mutable<ImmutableUser>; // 所有字段再次变为可修改3. 装饰器及其类型化
装饰器是TypeScript的实验性功能,广泛用于Angular和NestJS。面试中可能会被问到如何为类或方法装饰器添加类型。重要的是要理解装饰器只是一个接受目标对象并返回它(或新对象)的函数。
// 带类型化的类装饰器function Logger<T extends { new (...args: any[]): {} }>(constructor: T) { console.log(`Class ${constructor.name} created`); return class extends constructor { constructor(...args: any[]) { super(...args); console.log('Instance created'); } };}
@Loggerclass MyService { constructor(public name: string) {}}
const service = new MyService('Test'); // 控制台输出:"Class MyService created",然后 "Instance created"在高级问题中,可能会要求实现一个添加元数据或验证的装饰器。请注意泛型的使用——<T extends { n