如何在TypeScript中结合展开运算符与Parameters工具类型并修复类型错误
修复TypeScript缓存高阶函数的参数迭代器错误
我写了一个能缓存异步函数结果的高阶函数,传入相同参数时会返回缓存的Promise。但去掉//@ts-ignore注释后,TypeScript报错:Type 'Parameters<FN>' must have a '[Symbol.iterator]()' method that returns an iterator. ts(2488)。
原函数代码:
function memoize<FN extends (...args: any) => Promise<any>>(fn: FN) { const cache: Record<string, Promise<Awaited<ReturnType<FN>>>> = {}; return (...args: Parameters<FN>) => { const cacheKey = JSON.stringify(args); if (!(cacheKey in cache)) { // @ts-ignore const promise = fn(...args); cache[cacheKey] = promise; } return cache[cacheKey]; }; }
使用示例:
const cachedFunction = memoize(async (id: string) => fetch(`https://jsonplaceholder.typicode.com/todos/${id}`)) const resultFromAPI = cachedFunction("1") const resultFromCache = cachedFunction("1")
问题根源
原来的泛型约束FN extends (...args: any) => Promise<any>太宽泛,args: any允许函数参数是任意类型,TypeScript没法确定Parameters<FN>对应的参数列表是可迭代的元组,所以对fn(...args)的展开操作报错。
修复方法
只需要把泛型约束里的(...args: any)改成(...args: any[]),明确限定被包装的函数接收的是数组/元组类型的参数列表,这样TypeScript就能确定Parameters<FN>是可迭代的,展开操作就合法了。
修复后的代码:
function memoize<FN extends (...args: any[]) => Promise<any>>(fn: FN) { const cache: Record<string, Promise<Awaited<ReturnType<FN>>>> = {}; return (...args: Parameters<FN>) => { const cacheKey = JSON.stringify(args); if (!(cacheKey in cache)) { const promise = fn(...args); cache[cacheKey] = promise; } return cache[cacheKey]; }; }
补充说明
这个修改只是明确了参数类型的约束,不会影响函数的实际功能——原来的使用示例依然可以正常运行,同时TypeScript的类型检查也能通过,不需要再用//@ts-ignore来规避错误。
内容的提问来源于stack exchange,提问作者jansepke
相关产品推荐
相关产品推荐

