如何在TypeScript中为使用rest参数与属性注入的高阶函数正确类型标注?
TypeScript高阶函数wrap的类型标注方案
核心需求实现
我们需要让wrap函数满足两个类型检查要求:约束传入的fn2必须接收包含fn1的对象参数,同时约束返回函数的入参符合fn2参数去掉fn1后的要求。以下是修正后的类型标注方案:
首先明确已定义的基础类型(示例,以实际业务定义为准):
// 已在别处定义的类型 type Fn1Function = () => Promise<string>; type Fn2Return = Promise<number>;
最终实现代码
const wrap = <Fn2Param extends { fn1: Fn1Function }>( fn1: Fn1Function, fn2: (param: Fn2Param) => Fn2Return ): ((param: Omit<Fn2Param, "fn1">) => Fn2Return) => { return (param) => fn2({ fn1, ...param }); };
类型检查效果验证
1. 约束fn2必须接收含fn1的参数
泛型Fn2Param extends { fn1: Fn1Function }强制fn2的参数类型必须包含fn1: Fn1Function属性,不符合要求会直接报错:
// ❌ 类型错误:fn2的参数未包含fn1属性 wrap(async () => "test", (param: { id: number }) => Promise.resolve(123));
2. 约束返回函数的rest参数符合要求
返回函数的参数类型是Omit<Fn2Param, "fn1">,即fn2参数去掉fn1后的剩余属性,传入不符合要求的参数会触发错误:
// ✅ 正确示例:fn2参数包含fn1,返回函数传入合法参数 const wrappedFn = wrap( async () => "test", (param: { fn1: Fn1Function; id: number }) => Promise.resolve(param.id) ); wrappedFn({ id: 456 }); // 类型检查通过 // ❌ 错误示例:缺少必填的id属性 wrappedFn({}); // ❌ 错误示例:传入了未定义的name属性 wrappedFn({ id: 456, name: "test" });
原方案问题说明
你之前的方案中,泛型约束F extends (param: FirstParameter<F>) => Fn2Return没有限制FirstParameter<F>必须包含fn1属性,因此无法检测fn2参数是否符合要求。新方案通过直接约束Fn2Param的结构,补上了这个类型检查缺口。
内容的提问来源于stack exchange,提问作者ptrhvns
相关产品推荐
相关产品推荐

