You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让TypeScript自动推断函数返回值为元组而非数组?

让TypeScript自动推断getInvalidatorArgs返回值的元组类型

要解决TypeScript将getInvalidatorArgs返回对象的属性推断为数组而非元组的问题,核心是通过泛型约束建立invalidators中genSetKey的参数类型与getInvalidatorArgs返回值类型的强关联,让TypeScript自动识别元组类型,无需调用者手动添加类型注解。

步骤1:定义精确的Invalidator类型

先明确Invalidator的类型,将其genSetKey的参数类型作为泛型参数,确保元组类型能被后续泛型捕获:

type Invalidator<TArgs extends unknown[]> = {
  fn: () => void; // 可根据实际副作用逻辑调整fn的参数/返回值类型
  genSetKey: (...args: TArgs) => string; // 明确接收元组类型参数
};

步骤2:重构辅助函数的泛型定义

在辅助函数的泛型中,显式关联invalidators的结构与getInvalidatorArgs的返回值类型,强制TypeScript推断元组而非数组:

function createCachedFunction<
  TFnArgs extends unknown[],
  TFnReturn,
  // 捕获传入的invalidators的结构,保留每个genSetKey的参数元组类型
  TInvalidators extends Record<string, Invalidator<any>>,
  // 约束getInvalidatorArgs的返回值必须匹配每个invalidator的genSetKey参数元组
  TInvalidatorArgs extends {
    [K in keyof TInvalidators]: Parameters<TInvalidators[K]['genSetKey']>;
  }
>(
  primaryFn: (...args: TFnArgs) => TFnReturn,
  invalidators: TInvalidators,
  getInvalidatorArgs: (...args: TFnArgs) => TInvalidatorArgs
) {
  // 这里实现你的缓存逻辑:比如调用primaryFn后缓存结果,调用invalidator.fn时清除对应缓存键
  return (...args: TFnArgs) => {
    const result = primaryFn(...args);
    // 示例:获取invalidator参数并生成缓存键
    const invalidatorArgs = getInvalidatorArgs(...args);
    Object.entries(invalidators).forEach(([key, invalidator]) => {
      const setKey = invalidator.genSetKey(...invalidatorArgs[key as keyof TInvalidatorArgs]);
      console.log(`Cache key to invalidate: ${setKey}`);
    });
    return result;
  };
}

步骤3:使用示例(无需手动加类型注解)

调用辅助函数时,TypeScript会自动根据invalidators中genSetKey的参数类型,推断getInvalidatorArgs返回对象的属性为元组类型:

// 示例:可缓存的主函数
function getUser(name: string, lastName: string): { id: number; name: string } {
  return { id: 123, name: `${name} ${lastName}` };
}

// 示例:缓存失效器集合
const userInvalidators = {
  updateUser: {
    fn: () => console.log('Invalidating user cache'),
    genSetKey: (name: string, lastName: string) => `user:${name}:${lastName}`
  },
  deleteUser: {
    fn: () => console.log('Deleting user cache'),
    genSetKey: (userId: number) => `user:id:${userId}`
  }
};

// 调用辅助函数,无需任何手动类型注解
const cachedGetUser = createCachedFunction(
  getUser,
  userInvalidators,
  (name, lastName) => ({
    updateUser: [name, lastName], // 自动推断为[string, string]元组
    deleteUser: [123] // 自动推断为[number]元组
  })
);

// 测试调用
cachedGetUser('John', 'Doe');

原理说明

通过泛型TInvalidatorArgs约束为TInvalidators中每个genSetKey的参数元组的映射,TypeScript会基于invalidators的类型信息,自动将getInvalidatorArgs返回的数组字面量推断为匹配的元组类型,而非默认的宽泛数组类型(如string[])。

内容的提问来源于stack exchange,提问作者lentil-soup

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 19:32:27