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

TypeScript 如何在对象内约束函数签名 让onEnd参数匹配doAction返回类型

问题原因

你遇到的推导错误是TypeScript泛型推导优先级导致的死锁:
原写法将泛型T作为doAction返回Promise的内部类型,TS需要先确定doAction的返回值才能推导T,但你没有标注doAction的入参类型,TS又需要先知道T才能确定doAction的签名,最终T被推导为unknown,导致onEnd入参类型异常。

解决方案

重构泛型约束逻辑,让泛型直接匹配整个doAction函数类型,TS会优先用预设的入参约束推导doAction的参数类型,再提取返回值处理后赋值给onEnd的入参,完整实现如下:

export type $Unwrap<T> = T extends Promise<infer U>
    ? U
    : T extends (...args: any) => Promise<infer U>
    ? U
    : T extends (...args: any) => infer U
    ? U
    : T;

type DoActionArgType = { contactId: string };

// 提取doAction返回值并解包的工具类型
type UnwrapActionReturn<T extends (arg: DoActionArgType) => any> = $Unwrap<ReturnType<T>>;

// 泛型直接约束整个doAction函数
type Args<T extends (arg: DoActionArgType) => any> = 
{
  doAction: T;
  onEnd?: (arg: UnwrapActionReturn<T>) => void;
}

// 调整test函数的泛型约束
function test<T extends (arg: DoActionArgType) => any>(arg: Args<T>) {}

验证效果

你之前报错的场景可以正常运行,无需手动标注doAction入参类型:

test({
  doAction: async ({ contactId }) => 1, // contactId自动推导为string,返回值推导为Promise<number>
  onEnd: (arg) => {
    const a:number = arg // arg正确推导为number,无类型错误
  }
})

// 其他场景也全部兼容:
// 1. 外置doAction变量
const doAction = async ({ contactId }) => 1
test({ doAction, onEnd: (arg) => { const a:number = arg } })

// 2. 无入参的doAction
test({ doAction: async () => 'test', onEnd: (arg) => { const a:string = arg } })

// 3. 同步返回的doAction
test({ doAction: ({ contactId }) => true, onEnd: (arg) => { const a:boolean = arg } })

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 08:15:00