sindresorhus/is · error · TypeError

Expected value which is `Array`, received value of type `${i

Error message

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

What it means

Thrown by `assertArray(value)` when `Array.isArray(value)` is false. The library uses this assert to narrow `unknown` to `T[]`; the message reports the actual type via `is()` (e.g. 'Object', 'string', 'Set'). An optional per-element assertion runs only after this check passes.

Source

Thrown at source/index.ts:1436

		throw new TypeError('Invalid number of values');
	}

	if (!isAny(predicate, ...values)) {
		const predicates = Array.isArray(predicate) ? predicate as readonly Predicate[] : [predicate as Predicate];
		const expectedTypes = predicates.map(singlePredicate => isIsMethodName(singlePredicate.name) ? methodTypeMap[singlePredicate.name] : 'predicate returns truthy for any value');
		throw new TypeError(typeErrorMessageMultipleValues(expectedTypes, values));
	}
}

export function assertOptional<T>(value: unknown, assertion: (value: unknown, message?: string) => asserts value is T, message?: string): asserts value is T | undefined {
	if (!isUndefined(value)) {
		assertion(value, message);
	}
}

export function assertArray<T = unknown>(value: unknown, assertion?: (element: unknown, message?: string) => asserts element is T, message?: string): asserts value is T[] {
	if (!isArray(value)) {
		throw new TypeError(message ?? typeErrorMessage('Array', value));
	}

	if (assertion) {
		for (const element of value) {
			// @ts-expect-error: "Assertions require every name in the call target to be declared with an explicit type annotation."
			assertion(element, message);
		}
	}
}

export function assertArrayBuffer(value: unknown, message?: string): asserts value is ArrayBuffer {
	if (!isArrayBuffer(value)) {
		throw new TypeError(message ?? typeErrorMessage('ArrayBuffer', value));
	}
}

export function assertArrayLike<T = unknown>(value: unknown, message?: string): asserts value is ArrayLike<T> {
	if (!isArrayLike(value)) {

View on GitHub ↗ (pinned to 7821031c66)

Solutions

  1. Check what the caller actually passes and unwrap it (e.g. pass `response.data`, not `response`).
  2. Convert array-likes/iterables first: `Array.from(value)` or spread `[...value]`.
  3. If array-like is acceptable, use `assert.arrayLike` instead of `assert.array`.
  4. Normalize single-item inputs: `const list = Array.isArray(x) ? x : [x]` before asserting.

Example fix

// before
assert.array(document.querySelectorAll('li')); // NodeList, throws
// after
assert.array(Array.from(document.querySelectorAll('li')));
Defensive patterns

Strategy: type-guard

Validate before calling

if (!Array.isArray(value)) {
  // reject or normalize before calling assert.array(value)
}

Type guard

function isArrayOf(value, itemPredicate) {
  return Array.isArray(value) && (!itemPredicate || value.every(itemPredicate));
}

Try / catch

try {
  assert.array(value, is.string);
} catch (error) {
  if (error instanceof TypeError) { /* value was not an Array (or items failed) */ }
  else { throw error; }
}

Prevention

When it happens

Trigger: `assert.array(value)` receiving anything that is not a true Array: array-like objects (`arguments`, `NodeList`, `{length: 2}`), typed arrays, Sets, iterables, JSON objects with numeric keys, or a single item where a list was expected. A custom `message` argument replaces the default text.

Common situations: API/JSON responses returning a single object instead of an array (or a `{data: [...]}` wrapper being passed whole); DOM `querySelectorAll` results (NodeList, not Array); config files where a scalar was written instead of a YAML/JSON list; ORM results returning a cursor/iterable.

Related errors


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