microsoft/TypeScript · error · TypeError

Object is not iterable.

Error message

Object is not iterable.

What it means

`__values` downlevels for-of/spread. If the value has neither Symbol.iterator nor a numeric `.length`, and `Symbol.iterator` *does* exist on the runtime, it throws "Object is not iterable." — i.e. the runtime supports iteration but the value isn't iterable.

Source

Thrown at src/compiler/factory/emitHelpers.ts:1047

};

// ES2015 Destructuring Helpers

const valuesHelper: UnscopedEmitHelper = {
    name: "typescript:values",
    importName: "__values",
    scoped: false,
    text: `
            var __values = (this && this.__values) || function(o) {
                var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
                if (m) return m.call(o);
                if (o && typeof o.length === "number") return {
                    next: function () {
                        if (o && i >= o.length) o = void 0;
                        return { value: o && o[i++], done: !o };
                    }
                };
                throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
            };`,
};

// ES2015 Generator Helpers

// The __generator helper is used by down-level transformations to emulate the runtime
// semantics of an ES2015 generator function. When called, this helper returns an
// object that implements the Iterator protocol, in that it has `next`, `return`, and
// `throw` methods that step through the generator when invoked.
//
// parameters:
//  @param thisArg  The value to use as the `this` binding for the transformed generator body.
//  @param body     A function that acts as the transformed generator body.
//
// variables:
//  _       Persistent state for the generator that is shared between the helper and the
//          generator body. The state object has the following members:
//            sent() - A method that returns or throws the current completion value.

View on GitHub (pinned to b465fdbfe1)

Solutions

  1. Ensure the value is iterable (Array, Map, Set, generator, etc.) before iterating.
  2. Add a null/iterable guard around the loop.
  3. For plain objects use Object.entries/keys/values instead of for-of on the object.

Example fix

// before
const obj = { a: 1 };
for (const x of obj) { }   // throws "Object is not iterable."

// after
for (const x of Object.entries(obj)) { }
// or guard:
if (obj && obj[Symbol.iterator]) for (const x of obj) { }
Defensive patterns

Strategy: type-guard

Validate before calling

function assertIterable(v: unknown): void {
  if (v == null || (typeof (v as any)[Symbol.iterator] !== "function" && typeof (v as any).length !== "number")) {
    throw new TypeError("Object is not iterable.");
  }
}

Type guard

function isIterable<T>(v: unknown): v is Iterable<T> {
  return v != null && typeof (v as any)[Symbol.iterator] === "function";
}

Prevention

When it happens

Trigger: for-of (or spread/destructuring) over null, undefined, a plain object without an iterator, or any non-iterable non-array-like value.

Common situations: Iterating an object literal expecting entries; a function returning null where an iterable was expected; spreading a Map without calling .values()/.entries().

Related errors


AI-assisted analysis of microsoft/TypeScript@b465fdbfe1 (2026-08-12). Data as JSON: /api/errors/496aba346bb5e282. Report an issue: GitHub.