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

TypeScript如何移除函数对象字面量首个参数并保留类型?

TypeScript实现移除对象中所有函数首个参数并保留类型信息

需求说明

需要编写函数doSomething,接收一个值T和一个由函数组成的对象字面量:

  • 每个输入函数的首个参数固定为Proxy<T>类型
  • 返回结构完全一致的对象,但每个函数移除首个参数
  • 必须完整保留剩余参数和返回值的类型信息,避免参数退化为unknown[]

预期效果:

const res = doSomething('someVal', { func1: (proxy, other: string) => proxy.value + other });
res.func1('other string'); // 参数`other`被正确推断为string类型,返回值为string类型

问题分析

之前的尝试因类型定义过于嵌套复杂,导致要么返回函数参数变为unknown[],要么出现Target signature provides too few arguments编译错误,核心原因是泛型约束和类型推断逻辑不够直接。

解决方案

核心类型定义

首先定义一个通用类型,用于移除函数的首个参数:

type Proxy<T> = {
  value: T;
};

// 移除函数的首个参数,保留剩余参数和返回值类型
type OmitFirstParam<F> = F extends (first: any, ...rest: infer P) => infer R 
  ? (...rest: P) => R 
  : never;

函数实现

直接通过泛型约束输入对象,并映射返回类型:

function doSomething<T, M extends Record<string, (proxy: Proxy<T>, ...args: any[]) => any>>(
  value: T,
  methods: M
): { [K in keyof M]: OmitFirstParam<M[K]> } {
  // 实际逻辑:为每个方法绑定Proxy实例,此处用类型断言跳过实现细节
  return Object.fromEntries(
    Object.entries(methods).map(([key, fn]) => [
      key,
      (...args: any[]) => fn({ value }, ...args)
    ])
  ) as { [K in keyof M]: OmitFirstParam<M[K]> };
}

测试验证

// 调用示例,无编译错误
const res = doSomething('test', { 
  help: (proxy: Proxy<string>, a: number) => `${proxy.value}${a}`,
  greet: (proxy: Proxy<string>, name: string) => `Hello ${name}, my value is ${proxy.value}`
});

// 类型推断正确:res.help接收number参数,返回string
res.help(123); 
// res.greet接收string参数,返回string
res.greet("Alice");

解释

  • OmitFirstParam通过条件类型+infer直接提取函数的剩余参数和返回值,逻辑简洁且类型推断可靠
  • 泛型约束M extends Record<string, (proxy: Proxy<T>, ...args: any[]) => any>确保输入对象的每个函数都符合“首个参数为Proxy<T>”的要求
  • 返回类型通过映射类型{ [K in keyof M]: OmitFirstParam<M[K]> }直接将每个输入函数转换为移除首个参数后的版本,完全保留类型信息

内容的提问来源于stack exchange,提问作者Daniel Gimenez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 15:52:42