TypeScript中自定义可迭代对象for..of循环无法运行问题排查
看起来你的自定义可迭代对象代码逻辑本身是正确的,但问题大概率出在测试环境的配置或者TypeScript的类型/编译细节上。我来一步步帮你排查和解决:
1. 先验证迭代器本身是否正常工作
先给测试加一些调试代码,确认你的可迭代对象的迭代器是否能正常生成值:
test("can iterate custom", () => { // 先检查Symbol.iterator是否存在且是函数 console.log("Symbol.iterator type:", typeof myInterable[Symbol.iterator]); // 手动调用迭代器,查看返回值 const iterator = myInterable[Symbol.iterator](); console.log("First next():", iterator.next()); console.log("Second next():", iterator.next()); console.log("Third next():", iterator.next()); console.log("Fourth next():", iterator.next()); let total = 0; for (let i of myInterable) { console.log("Iterated value:", i); total += i; } expect(total).toBe(6); });
如果控制台输出里Symbol.iterator type是function,且前三次next()返回{value: 1/2/3, done: false},那迭代器本身没问题,问题出在for..of的执行环境;如果不是,那说明你的可迭代对象定义有问题。
2. 给可迭代对象添加明确的类型注解
TypeScript有时候无法自动推断手动添加Symbol.iterator的对象是可迭代类型,这可能导致编译后的代码存在隐性问题。给myInterable加上Iterable<number>类型注解试试:
let myInterable: Iterable<number> = { [Symbol.iterator]: numbers };
明确的类型会让TypeScript更准确地编译代码,避免一些隐性的转译错误。
3. 检查测试环境对生成器函数的支持
如果你的测试用的是Jest,可能存在转译工具没有正确处理生成器函数的情况:
- 确保你安装了
ts-jest和regenerator-runtime(生成器函数的运行时依赖):npm install --save-dev ts-jest regenerator-runtime - 在测试文件的顶部导入
regenerator-runtime:import 'regenerator-runtime/runtime'; - 检查你的Jest配置(
jest.config.js)是否正确使用了ts-jest作为转译器:module.exports = { preset: 'ts-jest', testEnvironment: 'node', };
4. 换用手动迭代器实现排除生成器问题
如果以上方法都没用,暂时替换成手动实现的迭代器,验证是否能正常迭代:
let myInterable: Iterable<number> = { [Symbol.iterator]() { let count = 1; return { next(): IteratorResult<number> { if (count <= 3) { return { value: count++, done: false }; } return { done: true }; } }; } };
如果这个版本能正常通过测试,说明问题出在生成器函数的转译/支持上,需要重点排查测试环境的生成器兼容配置。
最后检查编译后的代码
去你的编译输出目录(比如dist)找到对应的JS文件,查看myInterable的定义是否正确:
let myInterable = { [Symbol.iterator]: numbers };
如果这段代码被错误转译(比如变成了普通对象属性,而不是Symbol),那说明你的TypeScript编译配置有问题,需要重新确认target和lib是否确实设置为支持ES6的选项(你的当前配置看起来是对的,但可以再核对一遍)。
内容的提问来源于stack exchange,提问作者JustinM

