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

TypeScript复杂泛型与函数返回类型问题咨询

TypeScript复杂泛型与函数返回类型问题解决

先看原代码:

interface Example<
  Arg0,
  Arg1 extends (payload: ReturnType<Arg2>) => Arg0,
  Arg2 extends (payload: ReturnType<Arg3>) => any,
  Arg3 extends (...arg: any) => any
> {
  func: Arg1;
  func2: Arg2;
  func3: Arg3;
}

function test<
  T extends Example<Arg0, Arg1, Arg2, Arg3>,
  Arg0 = ReturnType<T["func"]>,
  Arg1 extends (payload: ReturnType<Arg2>) => any = T["func"],
  Arg2 extends (payload: ReturnType<Arg3>) => any = T["func2"],
  Arg3 extends (...arg: any) => any = T["func3"]
>(arg: Readonly<T>): Arg0 {
  return {} as any;
}

test({
  func: (payload) => 1, // payload类型为any,期望是{ test: number }
  func2: (payload) => {
    // payload类型为{ test: string },正确
    return { test: 1 };
  },
  func3: () => {
    return { test: "string" };
  },
}); // 返回值类型为number,正确

function test2<
  Arg0,
  Arg1 extends (payload: ReturnType<Arg2>) => Arg0,
  Arg2 extends (payload: ReturnType<Arg3>) => any,
  Arg3 extends (...arg: any) => any
>(arg: Example<Arg0, Arg1, Arg2, Arg3>): Arg0 {
  return {} as any;
}

test2({
  func: (payload) => 1, // payload类型为any,期望是{ test: number }
  func2: (payload) => {
    // payload类型为{ test: string },正确
    return { test: 1 };
  },
  func3: () => {
    return { test: "string" };
  },
}); // 返回值类型为unknown,期望是number

问题

  • test函数中,func的payload类型为any,期望约束为{ test: number }
  • test2函数中,返回值类型为unknown,期望是number

解决方案

问题1:约束test函数中func的payload类型

原代码的泛型参数顺序导致TypeScript优先推导顶层的T,无法将func2、func3的类型依赖反向传递给func的payload。调整泛型参数推导顺序,让TypeScript从最底层的Arg3开始推导,逐层向上传递类型约束:

function test<
  Arg3 extends (...arg: any) => any,
  Arg2 extends (payload: ReturnType<Arg3>) => any,
  Arg1 extends (payload: ReturnType<Arg2>) => any,
  Arg0 = ReturnType<Arg1>,
  T extends Example<Arg0, Arg1, Arg2, Arg3> = Example<Arg0, Arg1, Arg2, Arg3>
>(arg: Readonly<T>): Arg0 {
  return {} as any;
}

调整后,TypeScript会按func3→func2→func的顺序推导:

  1. 从func3得到返回值类型{ test: string },作为func2的payload类型
  2. 从func2得到返回值类型{ test: number },自动作为func的payload类型,符合预期

问题2:让test2函数返回值正确推导为number

test2的核心问题是泛型参数顺序错误,导致Arg0无法从func的返回值中推导,最终 fallback 为unknown。同样调整泛型参数推导顺序,让依赖链从底层到上层:

function test2<
  Arg3 extends (...arg: any) => any,
  Arg2 extends (payload: ReturnType<Arg3>) => any,
  Arg1 extends (payload: ReturnType<Arg2>) => any,
  Arg0 = ReturnType<Arg1>
>(arg: Example<Arg0, Arg1, Arg2, Arg3>): Arg0 {
  return {} as any;
}

现在调用test2时,TypeScript会依次推导:

  • Arg3的返回值→Arg2的参数类型
  • Arg2的返回值→Arg1的参数类型
  • Arg1的返回值→Arg0的类型,也就是函数的返回值类型,会正确推断为number,同时func的payload也会被约束为{ test: number }

如果想让代码逻辑更统一,可以同步调整Example接口的泛型参数顺序,让依赖关系更清晰:

interface Example<
  Arg3 extends (...arg: any) => any,
  Arg2 extends (payload: ReturnType<Arg3>) => any,
  Arg1 extends (payload: ReturnType<Arg2>) => any,
  Arg0 = ReturnType<Arg1>
> {
  func: Arg1;
  func2: Arg2;
  func3: Arg3;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 03:35:09