TypeScript:如何为通用高阶函数添加正确的类型约束
TypeScript工具函数
resolvePromises的类型定义问题 工具函数代码
async function resolvePromises<F extends (arg: any) => any>( data: Parameters<F>, list: F[] | F[][], ): Promise<boolean> { for (const item of list) { if (!Array.isArray(item)) { await item(data); continue; } await Promise.allSettled(item.map((action) => action(data))); } return true; }
正常调用示例
const wait = ({ time = 1000 }) => new Promise((resolve) => setTimeout(resolve, time)); resolvePromises({ time: 2000 }, [wait, wait]);
期望的类型校验效果
希望TypeScript能限制data参数必须与传入的Promise函数的参数类型严格匹配,比如以下传入多余属性的调用应该触发类型错误:
resolvePromises({ time: 2000, name: 'John' }, [wait, wait]);
当前存在的问题
resolvePromises的第一个参数data在类型提示中始终显示为数组类型,但wait这类目标函数的参数是单个对象,并非数组;- 若强行传入数组形式的
data,类型校验能工作,但这不符合实际业务中函数的参数要求; - 函数本身支持传入嵌套的Promise函数数组(如
[[wait, wait],[wait]]),但当前类型定义未完全适配这种嵌套场景下的参数一致性约束。
问题原因分析
Parameters<F>的误用:Parameters<F>返回的是函数F所有参数组成的元组类型,而非单个参数的类型。以wait函数为例,Parameters<typeof wait>的结果是[{ time?: number }](包含单个元素的元组),所以当前定义中data: Parameters<F>会要求传入一个数组,而非单个对象,直接导致了类型提示与实际参数要求的矛盾。- 泛型约束过于宽泛:泛型
F extends (arg: any) => any使用any作为参数类型,丢失了具体的参数类型信息,无法精准约束data与list中所有函数的参数类型保持一致。 - 嵌套数组的类型约束不足:虽然
list定义为F[] | F[][],但没有明确确保嵌套数组内的所有函数都和顶层函数共享相同的参数类型,不过这是次要问题,核心矛盾还是Parameters<F>导致的data类型错误。
内容的提问来源于stack exchange,提问作者jahilldev
相关产品推荐
相关产品推荐

