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

如何推断生成器产出的异步函数的返回类型?

解决TypeScript中异步生成器任务返回类型的推断问题

你遇到的问题是createSettlementSequence函数中,泛型T无法从生成器产出的异步函数自动推断为string,只能得到unknown,但J的类型能被正确推断。核心原因是当前泛型参数的声明顺序和依赖关系导致TypeScript无法反向推导T。

解决方案

调整泛型参数结构,不再单独声明T,而是通过条件类型从J中提取出对应的返回类型。这样TypeScript会先推断出J的完整类型,再自动推导T的值,同时保留J携带自定义元数据的能力。

修改后的代码

type Job<T> = () => Promise<T>

export interface JobFulfilment<T, J extends Job<T>> {
  job: J;
  status: "fulfilled";
  value: T;
}

export interface JobRejection<T, J extends Job<T>> {
  job: J;
  status: "rejected";
  reason: unknown;
}

export type JobSettlement<T, J extends Job<T>> =
  | JobFulfilment<T, J>
  | JobRejection<T, J>;

// 调整泛型参数,仅声明J,通过条件类型从J中提取T
export async function* createSettlementSequence<J extends Job<any>>(
  createJobSequence: () => AsyncGenerator<J>
): AsyncIterable<JobSettlement<J extends Job<infer T> ? T : never, J>> {
    for await (const job of createJobSequence()){
        try{
            const value = await job();
            yield {
                job,
                value,
                status:"fulfilled",
            } as JobFulfilment<J extends Job<infer T> ? T : never, J>
        }
        catch(reason){
            yield {
                job,
                reason,
                status:"rejected"
            } as JobRejection<J extends Job<infer T> ? T : never, J>
        }
    }
}

const settlementSequence = createSettlementSequence(async function* () {
    yield async () => "foo"
    yield async () => "bar"
    yield async () => "baz"
})

// 带元数据的场景同样能正确推断
const settlementSequenceWithMetadata = createSettlementSequence(async function* () {
    yield Object.assign(async () => "foo", { task: 0})
    yield Object.assign(async () => "bar", { task: 1})
    yield Object.assign(async () => "baz", { task: 2})
})

关键说明

  1. 泛型调整:将原函数的泛型<T, J extends Job<T>>改为<J extends Job<any>>,让TypeScript优先推断J的类型,避免T的推断阻塞。
  2. 类型提取:使用J extends Job<infer T> ? T : never从J中提取异步函数的返回类型T,确保JobSettlement中的T与J的实际返回值类型一致。
  3. 类型断言:在yield时添加类型断言,帮助TypeScript明确识别产出值的具体类型(否则可能因为联合类型的歧义导致推断不准确)。

这样修改后,settlementSequence的类型会被正确推断为AsyncIterable<JobSettlement<string, () => Promise<string>>>,带元数据的settlementSequenceWithMetadata也能正确保留元数据类型,同时T被推断为string。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 10:17:19