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
- Use the primitive literal or coercion function instead of the constructor: `String(x)` / `Number(x)` / `Boolean(x)` without `new`.
- Unwrap an existing boxed value with `.valueOf()` before passing it to the library.
- 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
- Never construct primitives with `new Boolean()/new Number()/new String()` — use literals or the function form without `new`
- Unwrap suspect values with `.valueOf()` before passing them to the library
- Enable lint rule `no-new-wrappers` (ESLint) to catch wrapper construction at build time
- Sanitize deserialized/third-party data at the boundary before type-checking it
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
- Expected value which is `Class`, received value of type `${i
- Expected value which is `empty map`, received value of type
- Expected value which is `empty object`, received value of ty
- Expected value which is `empty set`, received value of type
- Expected value which is `empty string`, received value of ty
AI-assisted analysis of sindresorhus/is@7821031c66 (2026-07-31).
Data as JSON: /data/errors/20e09f6cb8cdf971.json.
Report an issue: GitHub ↗.