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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 14:35:20