sindresorhus/is · error · TypeError

Expected value which is `GeneratorFunction`, received value

Error message

Expected value which is `GeneratorFunction`, received value of type `${is(value)}`.

What it means

Thrown by `assertGeneratorFunction()` when `isGeneratorFunction()` fails — the value's object tag is not `GeneratorFunction`. Only functions declared with `function*` pass; regular functions, async functions, and generator objects do not.

Source

Thrown at source/index.ts:1653

	}
}

// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
export function assertFunction(value: unknown, message?: string): asserts value is Function {
	if (!isFunction(value)) {
		throw new TypeError(message ?? typeErrorMessage('Function', value));
	}
}

export function assertGenerator(value: unknown, message?: string): asserts value is Generator {
	if (!isGenerator(value)) {
		throw new TypeError(message ?? typeErrorMessage('Generator', value));
	}
}

export function assertGeneratorFunction(value: unknown, message?: string): asserts value is GeneratorFunction {
	if (!isGeneratorFunction(value)) {
		throw new TypeError(message ?? typeErrorMessage('GeneratorFunction', value));
	}
}

export function assertHtmlElement(value: unknown, message?: string): asserts value is HTMLElement {
	if (!isHtmlElement(value)) {
		throw new TypeError(message ?? typeErrorMessage('HTMLElement', value));
	}
}

export function assertInfinite(value: unknown, message?: string): asserts value is number {
	if (!isInfinite(value)) {
		throw new TypeError(message ?? typeErrorMessage('infinite number', value));
	}
}

export function assertInRange(value: number, range: number | [number, number], message?: string): asserts value is number {
	if (!isInRange(value, range)) {
		throw new TypeError(message ?? typeErrorMessage('in range', value));

View on GitHub ↗ (pinned to 7821031c66)

Solutions

  1. Ensure the value is the raw `function*` declaration, not a wrapped, bound, or invoked form.
  2. Set the compile target to ES2017+ so generator syntax is preserved rather than transpiled by regenerator.
  3. For `async function*`, use `is.asyncGeneratorFunction` instead.

Example fix

// before (tsconfig)
"target": "ES5"
// after
"target": "ES2018"
Defensive patterns

Strategy: type-guard

Validate before calling

const GeneratorFunction = Object.getPrototypeOf(function* () {}).constructor;
if (!(value instanceof GeneratorFunction)) {
  throw new TypeError('Expected GeneratorFunction');
}

Type guard

function isGeneratorFunction(value: unknown): value is GeneratorFunction {
  return typeof value === 'function' && Object.prototype.toString.call(value) === '[object GeneratorFunction]';
}

Try / catch

try {
  assert.generatorFunction(value);
} catch (error) {
  if (error instanceof TypeError) { /* passed a normal function or a generator instance */ }
  else throw error;
}

Prevention

When it happens

Trigger: `is.assert.generatorFunction(value)` with a normal function, an arrow function, an async generator function (`async function*`, tagged differently), or an already-invoked generator object.

Common situations: Transpilers (older Babel/TypeScript targets like ES5) compile `function*` into regular functions using a regenerator runtime, destroying the `GeneratorFunction` tag; passing `gen()` where the function itself was expected; wrapping the generator function in `.bind()` or a decorator that returns a plain function.

Related errors


AI-assisted analysis of sindresorhus/is@7821031c66 (2026-07-31). Data as JSON: /data/errors/0f6cad263fc52839.json. Report an issue: GitHub ↗.