MST

星途 面试题库

面试题:TypeScript泛型在复杂异步场景下的类型优化

在一个复杂的前端应用中,有一个函数`processData`,它接收一个表示数据处理流程的数组,数组中的每个元素是一个异步函数,这些异步函数可能接收不同类型的参数并返回不同类型的结果,而且前一个函数的返回值可能是下一个函数的参数。请使用TypeScript泛型设计一个类型系统,确保整个数据处理流程的类型安全,并且在执行过程中能正确地进行类型推导和错误提示。请详细阐述设计思路和关键代码实现。
38.4万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 定义函数类型:使用TypeScript的泛型来定义每个异步函数的类型,使其能够接收不同类型参数并返回不同类型结果。
  2. 定义流程类型:定义一个类型来表示整个数据处理流程数组,确保每个元素的类型符合上述定义的函数类型,并且前一个函数的返回值类型与下一个函数的参数类型匹配。
  3. 执行函数:编写一个函数来执行这个数据处理流程,利用TypeScript的类型推导和类型检查功能,在编译时发现类型错误。

关键代码实现

// 定义一个类型来表示单个异步函数
type AsyncFunction<Args extends any[], Return> = (...args: Args) => Promise<Return>;

// 定义一个类型来表示整个数据处理流程
type DataProcessor<Steps extends AsyncFunction<any, any>[]> = {
    [K in keyof Steps]: K extends 0
      ? Steps[K]
       : (prevResult: ReturnType<Steps[K - 1]>) => ReturnType<Steps[K]>;
};

// 执行数据处理流程的函数
async function executeProcessor<Steps extends AsyncFunction<any, any>[]>(
    processor: DataProcessor<Steps>
): Promise<ReturnType<Steps[Steps['length'] - 1]>> {
    let result = await processor[0]();
    for (let i = 1; i < processor.length; i++) {
        result = await processor[i](result);
    }
    return result;
}

// 示例异步函数
const step1: AsyncFunction<[], number> = async () => 42;
const step2: (num: number) => Promise<string> = async (num) => num.toString();
const step3: (str: string) => Promise<boolean> = async (str) => str.length > 0;

// 定义数据处理流程
const dataProcessor: DataProcessor<[typeof step1, typeof step2, typeof step3]> = [step1, step2, step3];

// 执行数据处理流程
executeProcessor(dataProcessor).then((finalResult) => {
    console.log(finalResult);
});
  1. AsyncFunction类型:定义了一个通用的异步函数类型,Args是参数类型数组,Return是返回值类型。
  2. DataProcessor类型:使用映射类型来确保每个步骤的函数类型正确,并且前一个函数的返回值类型是下一个函数的参数类型。
  3. executeProcessor函数:执行数据处理流程,按照顺序依次调用每个步骤的函数,并传递前一个函数的返回值作为下一个函数的参数。
  4. 示例使用:定义了三个示例异步函数step1step2step3,组成一个数据处理流程dataProcessor,并通过executeProcessor函数执行该流程。在整个过程中,TypeScript会进行严格的类型检查,确保类型安全。