sindresorhus/is · error · TypeError

Please don't use object wrappers for primitive types

Error message

Please don't use object wrappers for primitive types

What it means

Thrown by the internal `is(value)` type-detection function when the value is a boxed primitive object such as `new String('x')`, `new Number(1)`, or `new Boolean(true)`. The library deliberately refuses to classify these because object wrappers behave surprisingly (e.g. `new Boolean(false)` is truthy) and are universally considered an anti-pattern; the check at source/index.ts:254 (`isBoxedPrimitiveObject`) runs just before the generic 'Object' fallback.

Source

Thrown at source/index.ts:255

	if (isArray(value)) {
		return 'Array';
	}

	if (isBuffer(value)) {
		return 'Buffer';
	}

	const tagType = getObjectType(value);
	if (tagType !== undefined && tagType !== 'Object') {
		return tagType;
	}

	if (hasPromiseApi(value)) {
		return 'Promise';
	}

	if (isBoxedPrimitiveObject(value)) {
		throw new TypeError('Please don\'t use object wrappers for primitive types');
	}

	return 'Object';
}

function hasPromiseApi<T = unknown>(value: unknown): value is Promise<T> {
	return isFunction((value as Promise<T>)?.then) && isFunction((value as Promise<T>)?.catch);
}

function hasBoxedPrimitiveBrand(value: unknown, valueOf: () => unknown): boolean {
	try {
		// `Object.prototype.toString` can be spoofed via `Symbol.toStringTag`, but the
		// boxed primitive `valueOf` methods still enforce the real internal brand.
		Reflect.apply(valueOf, value, []);
		return true;
	} catch {
		return false;
	}

View on GitHub ↗ (pinned to 7821031c66)

Solutions

  1. Use the primitive literal or coercion function instead of the constructor: `String(x)` / `Number(x)` / `Boolean(x)` without `new`.
  2. Unwrap an existing boxed value with `.valueOf()` before passing it to the library.
  3. If the wrapper comes from a third-party library, unwrap at the boundary where its values enter your code.

Example fix

// before
const name = new String('alice');
is(name); // throws TypeError

// after
const name = String('alice'); // or just 'alice'
is(name); // => 'string'
Defensive patterns

Strategy: validation

Validate before calling

const isObjectWrapper = (v) => v instanceof Boolean || v instanceof Number || v instanceof String;
if (isObjectWrapper(value)) value = value.valueOf();

Type guard

function isPrimitiveSafe(v: unknown): boolean {
  return !(v instanceof Boolean || v instanceof Number || v instanceof String);
}

Prevention

When it happens

Trigger: Calling `is(value)` (the default detect function) — or any assertion whose error message formats the value's type via `is(value)` — with a value created via `new String(...)`, `new Number(...)`, `new Boolean(...)`, `Object('str')`, or `Object(Symbol())`. Plain primitives ('x', 1, true) never trigger it.

Common situations: Legacy code or old libraries that construct primitives with `new`; values deserialized/wrapped by frameworks (e.g. some ORMs or template engines wrapping strings); accidentally writing `new Number(x)` instead of `Number(x)` when coercing; test fixtures using `Object('foo')`.

Related errors


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