MST

星途 面试题库

面试题:TypeScript泛型与类型保护函数结合的设计模式

设计一个通用的类型保护函数,它接收一个泛型类型 `T` 和一个值 `value`,并且 `T` 可以是一个联合类型,该函数能够智能地缩小 `value` 的类型范围到 `T` 联合类型中的某一个具体类型。例如,`type Example = { kind: 'a'; data: string; } | { kind: 'b'; data: number; };`,调用该类型保护函数,传入 `Example` 和一个符合 `Example` 联合类型的值,函数能够根据值的 `kind` 属性,正确地将值的类型缩小到具体的 `{ kind: 'a'; data: string; }` 或 `{ kind: 'b'; data: number; }` 类型,同时阐述如何通过类型推断和约束保证该函数在不同联合类型场景下的正确性和通用性。
24.1万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试
function typeGuard<T extends { kind: string }>(value: T, kind: string): value is Extract<T, { kind: typeof kind }> {
    return value.kind === kind;
}

// 示例用法
type Example = { kind: 'a'; data: string; } | { kind: 'b'; data: number; };
const example1: Example = { kind: 'a', data: 'test' };
const example2: Example = { kind: 'b', data: 123 };

if (typeGuard(example1, 'a')) {
    // example1 类型缩小为 { kind: 'a'; data: string; }
    console.log(example1.data.toUpperCase());
}

if (typeGuard(example2, 'b')) {
    // example2 类型缩小为 { kind: 'b'; data: number; }
    console.log(example2.data.toFixed(2));
}

类型推断和约束分析

  1. 泛型 T 的约束T 被约束为具有 kind 属性且类型为 string 的类型,这样确保传入的联合类型都有 kind 属性,为类型保护提供依据。
  2. Extract 类型操作符Extract<T, { kind: typeof kind }> 用于从联合类型 T 中提取出 kind 属性值与传入的 kind 参数匹配的类型,从而实现类型缩小。
  3. 返回值类型:通过 value is Extract<T, { kind: typeof kind }> 语法,告知 TypeScript 当函数返回 true 时,value 的类型可以缩小为 Extract<T, { kind: typeof kind }> 类型,从而在后续代码中实现智能类型推断。
  4. 通用性:由于 T 是泛型,并且仅依赖 kind 属性进行类型缩小,所以该函数可以适用于任何具有 kind 属性的联合类型场景,保证了通用性。