This error occurs when you use the yield keyword in a regular function instead of a generator function. Generator functions must be declared with the function* syntax (with an asterisk).
This TypeScript error occurs when you attempt to use the yield keyword inside a function that hasn't been declared as a generator function. In JavaScript and TypeScript, the yield keyword is a special operator that can only be used within generator functions, which are denoted by the function* syntax (note the asterisk). Generator functions are special functions that can pause their execution and resume later, yielding multiple values over time. When you call a generator function, it returns a generator object that implements the iterator protocol, allowing you to retrieve values one at a time using the next() method. The compiler enforces this restriction because using yield in a regular function would violate the language specification. Regular functions execute from start to finish in a single run, while generator functions maintain their state between yields and can be paused and resumed multiple times.
The most common fix is to change your function declaration to use the function* syntax:
// ❌ Wrong - regular function
function getNumbers() {
yield 1;
yield 2;
yield 3;
}
// ✅ Correct - generator function
function* getNumbers() {
yield 1;
yield 2;
yield 3;
}For class methods, add the asterisk before the method name:
class DataGenerator {
// ❌ Wrong
getData() {
yield 'data';
}
// ✅ Correct
*getData() {
yield 'data';
}
}TypeScript allows you to specify the type of values yielded by a generator function:
// Generator that yields numbers
function* numberGenerator(): Generator<number> {
yield 1;
yield 2;
yield 3;
}
// Generator with yield type, return type, and next parameter type
function* advancedGenerator(): Generator<number, string, boolean> {
const shouldContinue = yield 1;
if (shouldContinue) {
yield 2;
}
return 'done';
}The Generator<T, TReturn, TNext> type takes three type parameters:
- T: Type of values yielded by the generator
- TReturn: Type of the final return value (default: any)
- TNext: Type of values passed to .next() (default: unknown)
Arrow functions cannot be generators. If you need generator functionality, convert to a function declaration or expression:
// ❌ Wrong - arrow functions cannot be generators
const gen = () => {
yield 1;
};
// ✅ Correct - use function expression
const gen = function* () {
yield 1;
};
// ✅ Also correct - use function declaration
function* gen() {
yield 1;
}If you need the this context from an arrow function, consider using a regular generator with .bind() or restructuring your code.
Generator functions were introduced in ES2015 (ES6). Ensure your TypeScript configuration targets ES2015 or higher:
// tsconfig.json
{
"compilerOptions": {
"target": "ES2015", // or "ES6", "ES2020", "ESNext", etc.
"lib": ["ES2015"],
// If targeting ES5, enable downlevelIteration
"downlevelIteration": true
}
}If you must target ES5 or ES3, enable the downlevelIteration flag to allow TypeScript to emit helper code for generators. Note that this increases bundle size.
If you're composing generators, use yield* to delegate to another generator:
function* innerGenerator() {
yield 1;
yield 2;
}
function* outerGenerator() {
yield 0;
// Delegate to another generator
yield* innerGenerator();
yield 3;
}
const gen = outerGenerator();
console.log([...gen]); // [0, 1, 2, 3]This allows you to compose multiple generators while maintaining the generator context.
If you don't actually need lazy evaluation or the ability to pause execution, consider using regular functions with arrays:
// Instead of a generator
function* getNumbers() {
yield 1;
yield 2;
yield 3;
}
// Use a regular function returning an array
function getNumbers(): number[] {
return [1, 2, 3];
}
// Or return an iterator without using yield
function getNumbers(): IterableIterator<number> {
let index = 0;
return {
[Symbol.iterator]() {
return this;
},
next() {
if (index < 3) {
return { value: ++index, done: false };
}
return { value: undefined, done: true };
}
};
}Choose generators when you need lazy evaluation, infinite sequences, or stateful iteration.
Async Generators: TypeScript also supports async generators using async function* syntax, which allows you to use both await and yield together:
async function* fetchPages(urls: string[]): AsyncGenerator<Response> {
for (const url of urls) {
const response = await fetch(url);
yield response;
}
}Generator Types in Libraries: When working with libraries like Redux-Saga, you'll encounter typed generator functions extensively. The saga middleware relies on generator functions to manage side effects in a testable, synchronous-looking manner.
Performance Considerations: Generators create iterator objects and maintain state between yields, which has a small memory overhead compared to simple functions. For hot code paths processing millions of items, consider profiling before using generators.
Iterator Protocol: Generator functions automatically implement the iterable protocol, meaning they work with for...of loops, spread operators, and destructuring. This makes them powerful for creating custom iteration logic:
function* fibonacci(): Generator<number> {
let [prev, curr] = [0, 1];
while (true) {
yield curr;
[prev, curr] = [curr, prev + curr];
}
}
// Take first 10 fibonacci numbers
const first10 = [];
for (const num of fibonacci()) {
if (first10.length >= 10) break;
first10.push(num);
}Strict Mode: In strict mode (which TypeScript enables by default), using yield as a variable name is also prohibited, even outside generator functions.
Function expression requires a return type
Function expression requires a return type
Value of type 'string | undefined' is not iterable
How to fix "Value is not iterable" in TypeScript
Type 'undefined' is not assignable to type 'string'
How to fix "Type undefined is not assignable to type string" in TypeScript
Type narrowing from typeof check produces 'never'
How to fix "Type narrowing produces never" in TypeScript
Type parameter 'T' has conflicting constraints
How to fix "Type parameter has conflicting constraints" in TypeScript