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

如何在TypeScript中为Month类实现基于[Symbol.iterator]的可迭代性?

解决TypeScript中Month类迭代器的类型标注问题

问题根源

你在类中手动标注[Symbol.iterator]: () => Generator<Day, void, undefined>时,未明确生成器函数内this的类型,且TypeScript对可迭代对象的规范实现更推荐通过接口约束,而非直接标注属性类型。此外,构造函数中赋值的生成器函数若不指定this类型,TS无法推断其指向当前Month实例,导致类型检查报错。

两种可行解决方案

方案1:让类实现Iterable<Day>接口(推荐)

直接将[Symbol.iterator]作为类的方法定义,而非在构造函数中赋值,TS会自动校验迭代器类型,代码结构更清晰:

class Month implements Iterable<Day> {
  lang: string;
  name: string;
  number: number;
  year: number;
  numberOfDays: number;

  constructor(date = null, lang = 'default') {
    const day = new Day(null, lang);
    const monthsSize = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
    this.lang = lang;

    this.name = day.month;
    this.number = day.monthNumber;
    this.year = day.year;
    this.numberOfDays = monthsSize[this.number - 1];

    if (this.number === 2) {
      this.numberOfDays += isLeapYear(day.year) ? 1 : 0;
    }
  }

  // 直接定义迭代器方法,TS自动识别符合Iterable接口
  *[Symbol.iterator](): Generator<Day, void, undefined> {
    let number = 1;
    yield this.getDay(number);
    while (number < this.numberOfDays) {
      ++number;
      yield this.getDay(number);
    }
  }

  getDay(day: number) {
    return new Day(new Date(this.year, this.number - 1, day), this.lang);
  }
}

方案2:保留构造函数赋值,指定生成器的this类型

若坚持在构造函数中给[Symbol.iterator]赋值,需给生成器函数显式指定this类型为Month,让TS正确推断:

class Month {
  lang: string;
  name: string;
  number: number;
  year: number;
  numberOfDays: number;
  // 标注迭代器类型,同时确保生成器的this指向Month
  [Symbol.iterator]: (this: Month) => Generator<Day, void, undefined>;

  constructor(date = null, lang = 'default') {
    const day = new Day(null, lang);
    const monthsSize = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
    this.lang = lang;

    this.name = day.month;
    this.number = day.monthNumber;
    this.year = day.year;
    this.numberOfDays = monthsSize[this.number - 1];

    if (this.number === 2) {
      this.numberOfDays += isLeapYear(day.year) ? 1 : 0;
    }

    // 给生成器函数指定this类型
    this[Symbol.iterator] = function* (this: Month) {
      let number = 1;
      yield this.getDay(number);
      while (number < this.numberOfDays) {
        ++number;
        yield this.getDay(number);
      }
    };
  }

  getDay(day: number) {
    return new Day(new Date(this.year, this.number - 1, day), this.lang);
  }
}

验证代码

修改后,for...of循环可正常运行,TS不再报类型错误:

const month = new Month();

for (const day of month) {
  console.log(day.Date);
}

内容的提问来源于stack exchange,提问作者undefined-mind

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 04:24:16