TypeScript中如何描述作为泛型函数调用结果的函数返回类型
正确定义嵌套泛型函数的返回类型
我明白你的问题:你想让foo返回的bar函数,在调用bar<B>()时,返回值类型完全对应fn<B>()的执行结果,但目前TypeScript只能推导到unknown或者Promise<unknown>,根本没法正确识别泛型参数B带来的类型变化。
问题根源
你原来用ReturnType<typeof fn>作为bar的返回类型,这里的问题在于——typeof fn是泛型函数本身,不是传入具体泛型参数后的实例化版本。所以TypeScript只能给你一个最宽泛的默认类型(比如unknown),而不会关联到你调用bar时传入的B。
解决方案:用infer提取泛型函数的实例化返回类型
我们需要让TypeScript明确知道:bar的泛型参数B会传递给fn,并且bar的返回类型就是fn用B作为泛型参数后的返回值。可以通过类型推断(infer)来实现这一点:
function foo<Fn extends <X>() => unknown>(fn: Fn) { return function bar<B>(): Fn extends <X>() => infer R ? R : never { // 这里需要类型断言,因为TS暂时无法自动推导fn<B>()的类型匹配 return fn<B>({ /*config*/ }) as ReturnType<typeof fn<B>>; } }
验证示例
现在再跑你原来的测试代码,类型推导就完全符合预期了:
{ const f1 = <T>() => Promise.resolve(({/*input*/ } as T)); const x1 = foo(f1) const y1 = x1<{ a: 'A' }>()/** 现在推导为Promise<{ a: 'A'}> ✅*/.then(data => data.a); const y12 = x1<{ b: 'B' }>()/** 现在推导为Promise<{ b: 'B'}> ✅*/.then(data => data.b); } { const f2 = <T>() => ({/*input*/ } as T); const x2 = foo(f2) const y2 = x2<{ a: 'A' }>()/** 现在推导为{ a: 'A'} ✅*/.value const y21 = x2<{ b: 'B' }>()/** 现在推导为{ b: 'B'} ✅*/.value }
原理说明
- 我们给
foo的类型参数Fn限定为“接收泛型参数X的函数”,这样TypeScript能识别fn的泛型结构。 - 用
Fn extends <X>() => infer R提取出:当fn的泛型参数是X时,返回类型是R。 - 当
bar传入B时,X被替换为B,R就自动变成fn<B>()的返回类型。 - 最后用
as ReturnType<typeof fn<B>>做类型断言,是因为目前TypeScript的类型推导还没法自动关联这一步(这也是相关TS讨论的核心痛点),但这个断言是完全安全的,因为我们逻辑上已经确保了类型匹配。
内容的提问来源于stack exchange,提问作者maksimr
相关产品推荐
相关产品推荐

