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的顺序推导:
- 从
func3得到返回值类型{ test: string },作为func2的payload类型 - 从
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
相关产品推荐
相关产品推荐

