{"id":"20e09f6cb8cdf971","repo":"sindresorhus/is","slug":"please-don-t-use-object-wrappers-for-primitive-typ","errorCode":null,"errorMessage":"Please don't use object wrappers for primitive types","messagePattern":"Please don't use object wrappers for primitive types","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"source/index.ts","lineNumber":255,"sourceCode":"\tif (isArray(value)) {\n\t\treturn 'Array';\n\t}\n\n\tif (isBuffer(value)) {\n\t\treturn 'Buffer';\n\t}\n\n\tconst tagType = getObjectType(value);\n\tif (tagType !== undefined && tagType !== 'Object') {\n\t\treturn tagType;\n\t}\n\n\tif (hasPromiseApi(value)) {\n\t\treturn 'Promise';\n\t}\n\n\tif (isBoxedPrimitiveObject(value)) {\n\t\tthrow new TypeError('Please don\\'t use object wrappers for primitive types');\n\t}\n\n\treturn 'Object';\n}\n\nfunction hasPromiseApi<T = unknown>(value: unknown): value is Promise<T> {\n\treturn isFunction((value as Promise<T>)?.then) && isFunction((value as Promise<T>)?.catch);\n}\n\nfunction hasBoxedPrimitiveBrand(value: unknown, valueOf: () => unknown): boolean {\n\ttry {\n\t\t// `Object.prototype.toString` can be spoofed via `Symbol.toStringTag`, but the\n\t\t// boxed primitive `valueOf` methods still enforce the real internal brand.\n\t\tReflect.apply(valueOf, value, []);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/sindresorhus/is/blob/7821031c66cdeb7256a0feb2d506535f9e84fcaf/source/index.ts#L237-L273","documentation":"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.","triggerScenarios":"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.","commonSituations":"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')`.","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."],"exampleFix":"// before\nconst name = new String('alice');\nis(name); // throws TypeError\n\n// after\nconst name = String('alice'); // or just 'alice'\nis(name); // => 'string'","handlingStrategy":"validation","validationCode":"const isObjectWrapper = (v) => v instanceof Boolean || v instanceof Number || v instanceof String;\nif (isObjectWrapper(value)) value = value.valueOf();","typeGuard":"function isPrimitiveSafe(v: unknown): boolean {\n  return !(v instanceof Boolean || v instanceof Number || v instanceof String);\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["typescript","type-detection","boxed-primitive","anti-pattern"],"analyzedSha":"7821031c66cdeb7256a0feb2d506535f9e84fcaf","analyzedAt":"2026-07-31T18:34:06.268Z","schemaVersion":2}