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

TypeScript中如何指定Generator的next参数类型并保留yield类型推断?

解决生成器指定Next参数类型同时自动推断Yield类型的问题

当你显式指定Generator<unknown, unknown, Next>时,第一个泛型参数被硬编码为unknown,导致后续通过ReturnType提取的产出类型也变成unknown。下面提供几种可行的解决方案,既可以指定.next()的参数类型,又能让TypeScript自动推断生成器的产出类型:


方案1:类型断言指定Next类型(最简洁)

直接通过类型断言告诉TypeScript生成器的Next参数类型,同时保留自动推断的Yield类型:

// 定义你需要的Next参数类型
type Next = "continue" | "stop";

// 生成器函数:用类型断言指定Next类型,Yield类型自动推断
function* lex() {
  // cmd 的类型自动为 Next
  const cmd = yield { kind: "number", text: "123" };
  if (cmd === "stop") return;
  yield { kind: "char", text: "x" };
} as Generator<any, void, Next>;

// 提取产出类型作为Token
type Token = ReturnType<typeof lex> extends Generator<infer T, any, any> 
  ? T 
  : never;

// 类型验证
const gen = lex();
gen.next(); // ✅ 返回 { value: { kind: "number", text: "123" }, done: false }
gen.next("continue"); // ✅ 返回 { value: { kind: "char", text: "x" }, done: false }
gen.next("invalid"); // ❌ TypeScript报错:类型不匹配Next类型

方案2:条件类型验证并提取类型

不修改生成器函数写法,通过类型约束确保Next类型符合要求,同时提取Yield类型:

// 定义你需要的Next参数类型
type Next = { signal: "continue" | "stop" };

// 生成器函数:不指定返回类型,让TypeScript自动推断
function* lex() {
  const control = yield { kind: "number", text: "123" };
  // 手动指定control类型为Next,避免unknown/any
  const typedControl: Next = control;
  if (typedControl.signal === "stop") return;
  yield { kind: "char", text: "x" };
}

// 验证生成器的Next类型,不符合则返回never(触发报错)
type ValidatedGenerator = ReturnType<typeof lex> extends Generator<infer T, any, Next>
  ? Generator<T, any, Next>
  : never;

// 提取产出类型作为Token
type Token = ValidatedGenerator extends Generator<infer T, any, any>
  ? T
  : never;

// 使用时需指定实例类型为ValidatedGenerator
const gen: ValidatedGenerator = lex();
gen.next({ signal: "continue" }); // ✅ 正确
gen.next({ signal: "invalid" }); // ❌ TypeScript报错

方案3:泛型辅助类型(TypeScript 4.7+)

利用泛型辅助类型封装Next约束,代码更清晰:

type Next = string;

// 定义辅助类型:约束生成器的Next参数类型
type GeneratorWithNext<NextType> = Generator<any, unknown, NextType>;

// 生成器函数返回辅助类型,Yield类型自动推断
function* lex(): GeneratorWithNext<Next> {
  const input = yield { kind: "number", text: "123" };
  // input 的类型自动为 Next
  yield { kind: "char", text: input.charAt(0) };
}

// 提取产出类型作为Token
type Token = ReturnType<typeof lex> extends Generator<infer T, any, any>
  ? T
  : never;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:35:23