MST
星途 面试题库

面试题:TypeScript泛型约束在复杂场景下的应用

假设你正在开发一个类型安全的状态管理库,需要实现一个 `createSelector` 函数。该函数接受多个选择器函数(每个选择器函数接受一个全局状态对象并返回一个部分状态)和一个转换函数(接受所有选择器的返回值并返回最终结果)。请使用泛型约束确保:1. 每个选择器函数的输入类型正确;2. 转换函数的输入类型与选择器函数的返回类型匹配;3. `createSelector` 函数返回的结果类型与转换函数的返回类型匹配。请详细说明你的设计思路并实现该函数。
41.7万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 泛型定义
    • 为每个选择器函数的输入定义一个泛型 S,表示全局状态类型。
    • 为每个选择器函数的返回值定义不同的泛型,例如 R1, R2, ..., Rn,表示部分状态类型。
    • 为转换函数的返回值定义一个泛型 Result
  2. 类型约束
    • 确保每个选择器函数接受类型为 S 的全局状态对象。
    • 确保转换函数接受的参数类型与选择器函数的返回类型一一匹配。
    • 确保 createSelector 函数返回的结果类型与转换函数的返回类型 Result 匹配。

代码实现

type Selector<S, R> = (state: S) => R;

function createSelector<S, R1, R2, Result>(
  selector1: Selector<S, R1>,
  selector2: Selector<S, R2>,
  transform: (arg1: R1, arg2: R2) => Result
): (state: S) => Result;
function createSelector<S, R1, R2, R3, Result>(
  selector1: Selector<S, R1>,
  selector2: Selector<S, R2>,
  selector3: Selector<S, R3>,
  transform: (arg1: R1, arg2: R2, arg3: R3) => Result
): (state: S) => Result;
// 可以继续扩展更多选择器的重载

function createSelector<S, R1, R2, Result>(
  selector1: Selector<S, R1>,
  selector2: Selector<S, R2>,
  transform: (arg1: R1, arg2: R2) => Result
): (state: S) => Result {
  return (state: S) => {
    const result1 = selector1(state);
    const result2 = selector2(state);
    return transform(result1, result2);
  };
}

在上述代码中:

  1. 首先定义了 Selector 类型,它是一个函数类型,接受一个全局状态 S 并返回一个部分状态 R
  2. 然后使用函数重载定义了 createSelector 函数,不同的重载对应不同数量的选择器函数。每个重载都确保选择器函数的输入类型为 S,并且转换函数的输入类型与选择器函数的返回类型匹配。
  3. 最后实现了 createSelector 函数,它返回一个新的函数,该函数接受全局状态 S,调用每个选择器函数并将其结果传递给转换函数,最终返回转换函数的结果。