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

TypeScript如何修改函数类型返回新值?实现ReturnValueMapper泛型

关于TypeScript中替换函数返回值类型的实现方案

首先得明确:你最初写的ReturnValueMapper确实没法直接实现,因为TypeScript的类型系统里,没办法直接从泛型约束Func里提取出它的参数类型Args并复用——你写的Args[]在这里是未定义的类型参数,TypeScript没法自动推断它。不过别担心,我们有更优雅的方式来实现这个需求。

正确的ReturnValueMapper实现方式

我们可以利用TypeScript的条件类型和infer关键字来提取原函数的参数类型,然后重新构造一个参数相同但返回值替换的函数类型:

export type ReturnValueMapper<Func extends (...args: any[]) => any, ReturnValue> = 
  Func extends (...args: infer Args) => any 
    ? (...args: Args) => ReturnValue 
    : never;

这里的infer Args会自动从Func中提取出它的参数列表类型,然后我们用这个Args来构造新的函数类型,返回值替换成指定的ReturnValue。这样就完美实现了“保留原函数参数,替换返回值”的需求。

结合recompose的withStateHandlers优化场景

回到你的使用场景:你希望定义状态更新器时,不用显式指定Partial<State>,而是让类型系统自动适配。假设你的State类型是这样的:

interface State {
  name: string;
  age: number;
}

你可以用刚才的ReturnValueMapper来包装状态更新器的类型,或者直接在withStateHandlers的类型定义里整合这个逻辑。比如,我们可以自定义一个更友好的状态更新器类型:

// 定义一个通用的状态更新器类型,接收原函数(比如获取新状态的函数),替换返回值为void
type StateUpdater<State, UpdateFn extends (...args: any[]) => Partial<State>> = 
  ReturnValueMapper<UpdateFn, void>;

// 然后定义你的StateUpdaters
interface StateUpdaters {
  // 这里的update函数参数和原更新函数一致,但返回值是void
  update: StateUpdater<State, (field: string) => Partial<State>>;
}

或者更简洁地直接在StateUpdaters里使用条件类型:

interface StateUpdaters {
  update: ((field: string) => Partial<State>) extends (...args: infer Args) => any 
    ? (...args: Args) => void 
    : never;
}

这样你就不用在update方法里显式写Partial<State>了,类型系统会自动帮你处理返回值的替换,同时保留原参数类型。

为什么最初的写法不可行?

你最初的写法里Args[]是一个未声明的类型参数,TypeScript的泛型约束里不能直接引用未定义的类型参数。泛型参数必须在<>里显式声明,而你试图从Func中“提取”参数类型,但没有用infer来告诉TypeScript去推断这个类型,所以编译器无法识别Args是什么,自然会报错。


内容的提问来源于stack exchange,提问作者Leonid Fenko

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:34:40