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

TypeScript实现仅接受简单类型参数的memoize函数类型报错如何解决

问题原因
  • TS函数参数存在逆变特性,你定义的FuncWithSimpleParams参数类型是宽松的简单类型联合数组,你传入的函数参数是明确的更窄的string类型,不符合泛型约束的逆变检查规则,因此触发类型报错。
  • 代码存在运行时BUG:你声明cache为普通对象,却调用了仅Map实例存在的get方法,运行时会直接抛出异常。
修复后完整代码
// 定义允许的简单参数类型集合
type SimpleType = number | string | boolean | null | undefined;
// 约束入参函数的参数数组每一项都属于简单类型
type AllowedFunc<P extends SimpleType[], R> = (...args: P) => R;

export function memoize<P extends SimpleType[], R>(func: AllowedFunc<P, R>) {
  // 使用Map作为缓存载体,读写更符合预期
  const cache = new Map<string, R>();

  return function wrapper(...args: P): R {
    // 拼接缓存key时逐位转字符串,再用特殊分隔符拼接,避免不同参数组合撞key
    const cacheKey = args.map(String).join('||');
    if (cache.has(cacheKey)) {
      // 非空断言:已经判断存在,必然能取出值
      return cache.get(cacheKey)!;
    }
    const result = func(...args);
    cache.set(cacheKey, result);
    return result;
  };
}

// 调用测试,无类型报错
memoize(function (first: string, second: string) {
  return `${first}${second}`
})
修复说明
  • 调整泛型定义顺序:先声明参数数组泛型P和返回值泛型R,再约束P的每一项都是简单类型,避开了原写法触发的函数参数逆变检查,同时完整保留了传入函数的参数类型推导
  • 修复缓存读写逻辑:改用Map作为缓存载体,避免普通对象属性名和原型链属性冲突的问题,同时修复了原代码的方法调用错误
  • 优化缓存key生成逻辑:用特殊分隔符拼接参数,避免参数本身包含.时,不同参数组合生成相同key导致缓存混乱的问题

内容的提问来源于stack exchange,提问作者Adrian Adkison

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 13:45:03