如何在同一对象中使用某字段的参数类型作为另一字段的返回类型?
with函数返回类型与选中method参数类型严格匹配的问题 看起来你遇到的核心问题是:当在onSuccess里指定某个method时,with函数的返回类型没有被精确约束为该方法的参数类型,而是变成了所有方法参数类型的联合。这是因为原来的泛型设计让G默认是所有键的联合,导致类型推断范围太宽。
问题根源分析
原来的ReturnedObject泛型中,G extends keyof T = keyof T给G设置了默认值为所有方法键的联合,这就导致Parameters<...>会计算所有方法参数的联合类型。另外,你代码里的ReturnedObject<T>[G]是错误的引用——ReturnedObject的属性是property和onSuccess,你实际需要的是T[G]['q']的参数类型。
解决方案:用映射类型绑定method与with的类型
我们可以通过创建一个泛型的OnSuccess类型,让每个method和对应的with返回类型形成一一绑定的联合成员。这样TypeScript就能根据你指定的method自动窄化with的类型约束。
调整后的完整类型定义和使用示例如下:
// 定义辅助类型:提取指定方法的q函数的参数类型 type MethodParams<T, G extends keyof T> = Parameters<T[G]['q']>; // 定义OnSuccess类型:让每个method和对应的with返回类型绑定 type OnSuccess<T> = { [G in keyof T]: { method: G; with: () => MethodParams<T, G>; }; }[keyof T]; interface ReturnedObject<T> { property: string; onSuccess: OnSuccess<T>; } interface Option<T> { [key: string]: { q: (...args: any[]) => string | ReturnedObject<T>; }; } function fn<T extends Option<T>>() {}
测试验证
现在当你使用这个定义时,TypeScript会自动根据method的值约束with的返回类型:
fn({ method1: { q: (name: string) => 'hello!' + name, }, method2: { q: () => ({ property: 'value', onSuccess: { method: 'method1', with: () => ['Mo'], // ✅ 合法,完全匹配method1的参数类型[string] // with: () => [], // ❌ 报错:类型'[]'不能赋值给类型'[string]' } }) } });
为什么这个方案有效?
OnSuccess<T>是一个映射类型的联合:我们遍历T的所有键,为每个键生成一个{ method: G; with: () => ... }的对象,然后通过[keyof T]把这些对象转换成联合类型。当你在onSuccess中指定method: 'method1'时,TypeScript会自动将联合类型窄化到对应的成员,从而with的返回类型就被精确约束为method1的参数类型,而不是所有方法的联合类型。
内容的提问来源于stack exchange,提问作者Chemss-Eddine BenHassine

