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

如何实现TypeScript方法调用后交替切换返回类型?

实现方法返回类型的交替切换

问题描述

能否让类的方法交替返回两种不同类型?示例如下:

const i = new Intersperse<number, string>();

i.next(); // 期望返回 number
i.next(); // 期望返回 string
i.next(); // 期望返回 number
i.next(); // 期望返回 string

尝试用asserts仅能切换实例类型,但无法让方法返回值:

class Intersperse<Item, Separator, NextIsSeparator extends boolean = false> {
    next(): asserts this is Intersperse<Item, Separator, NextIsSeparator extends true ? false : true> {
        // 无法返回值
    } 
}

const i: Intersperse<number, string> = new Intersperse();

背景:正在复刻Rust的std::iter::Iterator::intersperse,可以将返回类型设为Item | Separator,但想尝试在类型层面实现严格的交替返回(尽管实用性不高)。

解决思路与实现

通过泛型状态标记+条件返回类型+this类型断言可以实现,核心是让next方法既返回对应类型的值,同时修改实例的泛型状态:

class Intersperse<Item, Separator, NextIsSeparator extends boolean = false> {
  private currentItemIndex = 0;
  private items: Item[];
  private separator: Separator;
  private nextIsSeparator: NextIsSeparator = false as NextIsSeparator;

  constructor(items: Item[], separator: Separator) {
    this.items = items;
    this.separator = separator;
  }

  next(): NextIsSeparator extends false ? Item : Separator {
    if (!this.nextIsSeparator) {
      const result = this.items[this.currentItemIndex++] as ReturnType<this['next']>;
      // 切换下一次的返回状态
      (this as unknown as Intersperse<Item, Separator, true>).nextIsSeparator = true as true;
      return result;
    } else {
      const result = this.separator as ReturnType<this['next']>;
      // 切换下一次的返回状态
      (this as unknown as Intersperse<Item, Separator, false>).nextIsSeparator = false as false;
      return result;
    }
  }
}

// 使用示例
const i = new Intersperse([1, 2, 3], ",");
const n1 = i.next(); // 类型为 number
const s1 = i.next(); // 类型为 string
const n2 = i.next(); // 类型为 number
const s2 = i.next(); // 类型为 string
const n3 = i.next(); // 类型为 number

关键细节

  • 用NextIsSeparator泛型标记下一次返回的类型状态,默认false表示首次返回Item
  • next方法的返回类型通过条件类型NextIsSeparator extends false ? Item : Separator实现严格交替
  • 通过类型断言修改实例的泛型状态,让TypeScript识别下一次调用的返回类型
  • 私有属性nextIsSeparator跟踪运行时状态,保证逻辑与类型提示一致

替代方案(实用优先)

如果不需要极致的类型精度,直接返回Item | Separator是更简洁的选择,实际项目中实用性更高:

class Intersperse<Item, Separator> {
  private currentItemIndex = 0;
  private items: Item[];
  private separator: Separator;
  private nextIsSeparator = false;

  constructor(items: Item[], separator: Separator) {
    this.items = items;
    this.separator = separator;
  }

  next(): Item | Separator {
    if (!this.nextIsSeparator) {
      this.nextIsSeparator = true;
      return this.items[this.currentItemIndex++];
    } else {
      this.nextIsSeparator = false;
      return this.separator;
    }
  }
}

内容的提问来源于stack exchange,提问作者k-tten

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 20:50:34