TypeScript error

TS2488: A value that is not iterable

  • Error TS2488
  • Tested with TypeScript 5.9

error TS2488: Type '{ theme: string; language: string; }' must have a '[Symbol.iterator]()' method that returns an iterator. is reported when for...of, array destructuring (const [a] = value) or array spread ([...value]) is used on a value that cannot be iterated. At run time the same code throws TypeError: settings is not iterable.

Plain objects are not iterable in JavaScript, even though for...in walks their keys. Arrays, strings, Map, Set and the results of Object.entries, Object.keys and Object.values are.

At a glance

CodeTS2488
MessageType '{0}' must have a '[Symbol.iterator]()' method that returns an iterator.
TypeScript's categoryerror
Listed underTypes do not match
Turned on by No option: every checked file reports it
In .js files Reported when the file is checked: checkJs in jsconfig.json, or // @ts-check at the top of the file

The message is TypeScript's own text from its diagnostic messages file (Apache-2.0); {0} is filled in by tsc for each error.

What it looks like

settings.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: settings.js(4,28): error TS2488: Type '{ theme: string; language: string; }' must have a '[Symbol.iterator]()' method that returns an iterator. settings.js(9,7): error TS2488: Type '{ theme: string; language: string; }' must have a '[Symbol.iterator]()' method that returns an iterator. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. settings.js(4,28): error TS2488: Type '{ theme: string; language: string; }' must have a '[Symbol.iterator]()' method that returns an iterator. settings.js(9,7): error TS2488: Type '{ theme: string; language: string; }' must have a '[Symbol.iterator]()' method that returns an iterator. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. settings.js(4,28): error TS2488: Type '{ theme: string; language: string; }' must have a '[Symbol.iterator]()' method that returns an iterator. settings.js(9,7): error TS2488: Type '{ theme: string; language: string; }' must have a '[Symbol.iterator]()' method that returns an iterator. checked 21 October 2026
const settings = { theme: "dark", language: "en-US" };

for (const [key, value] of settings) {error TS2488: Type '{ theme: string; language: string; }' must have a '[Symbol.iterator]()' method that returns an iterator.
  console.log(key, value);
}

const [firstSetting] = settings;error TS2488: Type '{ theme: string; language: string; }' must have a '[Symbol.iterator]()' method that returns an iterator.

export { firstSetting };
for...of and array destructuring on a plain object.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}

What causes it

  • A plain object is used where an iterable is needed, often a settings or lookup object that was an array or a Map in an earlier version of the code.
  • A value that may be undefined is destructured, and the message shows undefined in the type; a for...of over such a value is reported as TS18048 instead.

How to fix it

Iterate Object.entries, keys or values

for (const [key, value] of Object.entries(settings)) gives each pair, typed as [string, string] here. If the lookup is consulted and changed often, a Map is iterable by itself and keeps insertion order.

settings.js TypeScript 5.9.3 TypeScript 5.9.3, run 21 October 2026: No errors. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. No errors. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. No errors. checked 21 October 2026
const settings = { theme: "dark", language: "en-US" };

for (const [key, value] of Object.entries(settings)) {
  console.log(key, value);
}

const [firstSetting] = Object.keys(settings);

const lookup = new Map(Object.entries(settings));
for (const [key, value] of lookup) {
  console.log(key, value);
}

export { firstSetting };
Object.entries gives an iterable list of pairs.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}

Gotchas

  • Object.entries types keys as string, not as the object's property names, because an object may carry more properties than its type lists.
  • for (const key in settings) is allowed on a plain object, but reading settings[key] inside it is TS7053, because key is typed as string.

Sources

Last reviewed 20 October 2026.