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
yieldis valid only insidefunction*orasync function*.- An arrow function cannot be a generator: there is no
*() => {}orasync* () => {}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
yielditself. - If you need a lazy sequence, use
function*; if you need an asynchronous one, useasync function*.
Quick example
// 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
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:
// 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:
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/awaitfor an asynchronous flow of values; - build the iterator by hand with
Symbol.iteratororSymbol.asyncIterator.
async function* asyncGen() {
yield await Promise.resolve('data');
}
// Not allowed: there is no async generator arrow in the language
// const asyncGen = async* () => { ... };| Question | Answer |
|---|---|
Can you use yield in an arrow function? | No |
| Why? | yield is allowed only inside function* or async function* |
| Alternative | Declare 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
yieldwithawait.awaitis available in any async function, including an arrowasync () => {}, whileyieldis tied to generators. - Expecting
yieldto work in a nested function or callback inside a generator. Every function has its own body, so the outer generator'syieldis out of reach there. - Putting a star on an arrow:
const g = *() => {}orconst 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 readyA concise answer to help you respond confidently on this topic during an interview.