如何在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
相关产品推荐
相关产品推荐

