isPrimitiveObject
Determines whether a value is a primitive object with enhanced type safety. Uses the Object() constructor behavior to identify values that are objects when passed through Object(), which includes both primitive values that get wrapped and actual objects. This function has nuanced behavior and should be used with understanding of JavaScript's object coercion rules.
Signature
const isPrimitiveObject: <T extends object>(value: unknown) => value is T
Parameters
| Name | Type | Description |
|---|---|---|
value | - | Value to test for primitive object characteristics |
Returns
Type-safe boolean indicating whether Object(value) === value
Examples
Basic primitive object detection
import { isPrimitiveObject } from '@winglet/common-utils';
// True cases - objects (including boxed primitives)
console.log(isPrimitiveObject({})); // true (plain object)
console.log(isPrimitiveObject([])); // true (array)
console.log(isPrimitiveObject(new Date())); // true (Date object)
console.log(isPrimitiveObject(new String('test'))); // true (boxed string)
console.log(isPrimitiveObject(new Number(42))); // true (boxed number)
console.log(isPrimitiveObject(new Boolean(true))); // true (boxed boolean)
console.log(isPrimitiveObject(() => {})); // true (function)
console.log(isPrimitiveObject(/regex/)); // true (RegExp)
// False cases - primitives that get wrapped by Object()
console.log(isPrimitiveObject('string')); // false (primitive string)
console.log(isPrimitiveObject(42)); // false (primitive number)
console.log(isPrimitiveObject(true)); // false (primitive boolean)
console.log(isPrimitiveObject(Symbol('test'))); // false (symbol)
console.log(isPrimitiveObject(null)); // false (null becomes empty object)
console.log(isPrimitiveObject(undefined)); // false (undefined becomes empty object)
Understanding Object coercion behavior
function demonstrateObjectCoercion(value: unknown) {
const objectified = Object(value);
const isPrimObj = isPrimitiveObject(value);
console.log('Original:', value);
console.log('Object(value):', objectified);
console.log('Are they same reference?', objectified === value);
console.log('isPrimitiveObject:', isPrimObj);
console.log('---');
}
// Demonstrates the difference
demonstrateObjectCoercion('hello'); // false - string becomes String object
demonstrateObjectCoercion(42); // false - number becomes Number object
demonstrateObjectCoercion({}); // true - object remains same reference
demonstrateObjectCoercion([1, 2, 3]); // true - array remains same reference
Type filtering in mixed arrays
function separateObjectsFromPrimitives(values: unknown[]) {
const objects: object[] = [];
const primitives: (string | number | boolean | symbol | null | undefined)[] = [];
for (const value of values) {
if (isPrimitiveObject(value)) {
objects.push(value);
} else {
primitives.push(value as any);
}
}
return { objects, primitives };
}
// Usage
const mixed = [
'hello', 42, {}, [], new Date(), true, null, () => {}, Symbol('test')
];
const separated = separateObjectsFromPrimitives(mixed);
console.log('Objects:', separated.objects); // [{}, [], Date, function]
console.log('Primitives:', separated.primitives); // ['hello', 42, true, null, Symbol(test)]
Serialization preparation
function prepareForSerialization(data: unknown): any {
if (!isPrimitiveObject(data)) {
// Primitive values can be serialized directly
return data;
}
if (Array.isArray(data)) {
return data.map(prepareForSerialization);
}
if (data instanceof Date) {
return data.toISOString();
}
if (data instanceof RegExp) {
return { __regex: data.source, __flags: data.flags };
}
if (typeof data === 'function') {
return { __function: data.toString() };
}
if (data && typeof data === 'object') {
const result: any = {};
for (const [key, value] of Object.entries(data)) {
result[key] = prepareForSerialization(value);
}
return result;
}
return data;
}
Deep clone utility consideration
function needsDeepCloning(value: unknown): boolean {
if (!isPrimitiveObject(value)) {
// Primitives don't need cloning - they're copied by value
return false;
}
// Objects need consideration for deep cloning
return true;
}
function smartClone(value: unknown): unknown {
if (!needsDeepCloning(value)) {
return value; // Primitives are already "cloned" by assignment
}
// Handle different object types
if (Array.isArray(value)) {
return value.map(smartClone);
}
if (value instanceof Date) {
return new Date(value.getTime());
}
if (value && typeof value === 'object') {
const result: any = {};
for (const [key, val] of Object.entries(value)) {
result[key] = smartClone(val);
}
return result;
}
return value;
}
Memory usage analysis
function analyzeValue(value: unknown) {
const analysis = {
type: typeof value,
isPrimitiveObject: isPrimitiveObject(value),
memoryConsideration: '',
canHaveProperties: false
};
if (analysis.isPrimitiveObject) {
analysis.memoryConsideration = 'Stored by reference, may have properties';
analysis.canHaveProperties = true;
} else {
analysis.memoryConsideration = 'Stored by value, cannot have properties';
analysis.canHaveProperties = false;
}
return analysis;
}
// Usage examples
console.log(analyzeValue('hello')); // primitive string
console.log(analyzeValue({})); // object
console.log(analyzeValue([])); // array object
console.log(analyzeValue(42)); // primitive number
Playground
import { isPrimitiveObject } from '@winglet/common-utils'; // True cases - objects (including boxed primitives) console.log(isPrimitiveObject({})); // true (plain object) console.log(isPrimitiveObject([])); // true (array) console.log(isPrimitiveObject(new Date())); // true (Date object) console.log(isPrimitiveObject(new String('test'))); // true (boxed string) console.log(isPrimitiveObject(new Number(42))); // true (boxed number) console.log(isPrimitiveObject(new Boolean(true))); // true (boxed boolean) console.log(isPrimitiveObject(() => {})); // true (function) console.log(isPrimitiveObject(/regex/)); // true (RegExp) // False cases - primitives that get wrapped by Object() console.log(isPrimitiveObject('string')); // false (primitive string) console.log(isPrimitiveObject(42)); // false (primitive number) console.log(isPrimitiveObject(true)); // false (primitive boolean) console.log(isPrimitiveObject(Symbol('test'))); // false (symbol) console.log(isPrimitiveObject(null)); // false (null becomes empty object) console.log(isPrimitiveObject(undefined)); // false (undefined becomes empty object)
Notes
Technical Behavior:
- Returns
truewhenObject(value) === value(same reference) - Objects remain the same when passed through Object()
- Primitives get wrapped in objects, creating new references
- Functions are objects in JavaScript, so they return
true
Key Understanding:
- This is NOT the same as "is this a primitive type"
- This determines if something behaves as an object reference
- Useful for understanding memory and reference behavior
- Important for serialization and cloning decisions
Use Cases:
- Memory usage analysis
- Serialization/deserialization logic
- Deep clone optimization
- Reference vs value semantics determination
- Type system utilities
Performance: Single Object() constructor call with reference comparison.
Related Functions:
- Use
isPrimitiveType()for actual primitive type checking - Use
typeoffor basic type checking - Use
isObject()for general object detection - Use
Object.prototype.toString.call()for precise type detection