Skip to main content

Yield inside an arrow function

yield cannot be used inside an arrow function. The yield operator is allowed only in the body of a generator function (function* or async function*), and the arrow syntax has no generator form, so any attempt to write such code ends in a syntax error.

Theory

TL;DR

  • yield is valid only inside function* or async function*.
  • An arrow function cannot be a generator: there is no *() => {} or async* () => {} in the ECMAScript standard.
  • The error happens at parse time, which means the whole file or module never runs.
  • An arrow inside a generator is perfectly fine, as long as it does not contain yield itself.
  • If you need a lazy sequence, use function*; if you need an asynchronous one, use async function*.

Quick example

javascript
// Not allowed: an arrow function cannot be a generator const badGen = () => { yield 1; // SyntaxError }; // Correct: a generator function function* goodGen() { yield 1; yield 2; } console.log([...goodGen()]); // [1, 2]

Why an arrow cannot be a generator

An arrow function is a shorter syntax for an ordinary function, but with deliberately reduced semantics: it has no own this, arguments, super or new.target, it cannot be called with new, and it lacks the internal slot a generator needs.

A generator, in contrast, is a separate kind of function. Calling it does not execute the body: it returns an iterator object and keeps the execution state between next() calls. That suspend and resume machinery is exactly what yield drives.

In the specification yield is a YieldExpression, and the grammar permits it only inside a GeneratorBody or an AsyncGeneratorBody. An arrow body is neither production, so the parser never treats yield there as an operator.

What happens in practice

javascript
const gen = () => { yield 1; // SyntaxError };

The error surfaces before any code runs, while the source is being parsed. The exact text depends on the engine: V8 reports something like SyntaxError: Unexpected number, other engines phrase it differently, but the outcome is the same, the script does not start.

One extra nuance: outside a generator in sloppy mode yield is an ordinary identifier, so the engine first reads it as a variable name and only then trips over the next token. In strict mode and in ES modules yield is a reserved word, and the message differs again. Do not read too much into the wording, the cause is always the same.

The right way: function*

When you need yield, declare a generator explicitly:

javascript
// Declaration form function* gen() { yield 1; yield 2; } // Anonymous expression form const gen2 = function* () { yield 'A'; yield 'B'; }; // Method shorthand inside an object const source = { *items() { yield 'first'; yield 'second'; }, }; console.log([...gen()]); // [1, 2] console.log([...gen2()]); // ['A', 'B'] console.log([...source.items()]); // ['first', 'second']

The star may sit on either side of the space: function* gen() and function *gen() are equivalent. What matters is that it belongs to the function keyword, which an arrow simply does not have.

Arrows inside a generator

The ban applies to the arrow's own body, not to its neighbourhood. Inside a generator, arrows behave as usual:

javascript
function* gen() { const nums = [1, 2, 3]; yield nums.map(n => n * 2); // the arrow is a plain callback, no yield inside } console.log(gen().next().value); // [2, 4, 6]

Here the arrow is an ordinary function and does not use yield, so everything works. Note that yield does not leak into nested functions: even a regular function declared inside a generator cannot yield from the outer generator, because every function has its own body and its own suspension context.

Alternatives and a summary table

When you want yield-like behaviour in arrow style, one of three options usually covers it:

  • wrap the logic in a function* generator and return the finished result from it;
  • use async/await for an asynchronous flow of values;
  • build the iterator by hand with Symbol.iterator or Symbol.asyncIterator.
javascript
async function* asyncGen() { yield await Promise.resolve('data'); } // Not allowed: there is no async generator arrow in the language // const asyncGen = async* () => { ... };
QuestionAnswer
Can you use yield in an arrow function?No
Why?yield is allowed only inside function* or async function*
AlternativeDeclare a function* or an async function*
Can you call an arrow inside a generator?Yes, if it does not contain yield itself
Is there an arrow generator *=>?No, the standard does not define one

Common mistakes

  • Assuming *() => {} is merely "not supported by browsers yet". It is not a support question: the grammar does not exist in the specification and is not planned.
  • Confusing yield with await. await is available in any async function, including an arrow async () => {}, while yield is tied to generators.
  • Expecting yield to work in a nested function or callback inside a generator. Every function has its own body, so the outer generator's yield is out of reach there.
  • Putting a star on an arrow: const g = *() => {} or const g = () => * {}. Both are invalid.
  • Thinking the error appears at call time. It appears at parse time, so the whole module fails, not just one function.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.