Install
yarn add @httpx/plain-object
Features
- 👉 Provide isPlainObject and assertPlainObject functions.
- 👉 Convenience PlainObject type.
- 👉 Faster than most alternatives, see benchmarks.
- 👉 Lightweight (starts at ~100B) and node, browser and edge support.
- 👉 Available in ESM and CJS formats.
Documentation
👉 Official website or Github Readme
Usage
isPlainObject
import { isPlainObject } from '@httpx/plain-object';
// ✅👇 True
isPlainObject({ key: 'value' }); // ✅
isPlainObject({ key: new Date() }); // ✅
isPlainObject(new Object()); // ✅
isPlainObject(Object.create(null)); // ✅
isPlainObject({ nested: { key: true} }); // ✅
isPlainObject(new Proxy({}, {})); // ✅
isPlainObject({ [Symbol('tag')]: 'A' }); // ✅
// ✅👇 (node context, workers, ...)
const runInNewContext = await import('node:vm').then(
(mod) => mod.runInNewContext
);
isPlainObject(runInNewContext('({})')); // ✅
// ❌👇 False
class Test { };
isPlainObject(new Test()) // ❌
isPlainObject(10); // ❌
isPlainObject(null); // ❌
isPlainObject('hello'); // ❌
isPlainObject([]); // ❌
isPlainObject(new Date()); // ❌
isPlainObject(Math); // ❌ Static built-in classes
isPlainObject(Promise.resolve({})); // ❌
isPlainObject(Object.create({})); // ❌
assertPlainObject
import { assertPlainObject } from '@httpx/plain-object';
import type { PlainObject } from '@httpx/plain-object';
function fn(value: unknown) {
// 👇 Throws `new TypeError('Not a plain object')` if not a plain object
assertPlainObject(value);
// 👇 Throws `new TypeError('Custom message')` if not a plain object
assertPlainObject(value, 'Custom message');
// 👇 Throws custom error if not a plain object
assertPlainObject(value, () => {
throw new HttpBadRequest('Custom message');
});
return value;
}
try {
const value = fn({ key: 'value' });
// ✅ Value is known to be PlainObject<unknown>
assertType<PlainObject>(value);
} catch (error) {
console.error(error);
}
PlainObject type
Generic
ìsPlainObject
and assertPlainObject
accepts a generic to provide type
autocompletion. Be aware that no runtime check are done. If you’re looking for
runtime validation, check zod, valibot or other alternatives.
import { isPlainObject } from '@httpx/plain-object';
import type { PlainObject } from '@httpx/plain-object';
type CustomType = {
id: number;
data?: {
test: string[];
attributes?: {
url?: string | null;
caption?: string | null;
alternativeText?: string | null;
} | null;
} | null;
};
const value = { id: 1 } as unknown;
if (isPlainObject<CustomType>(value)) {
// ✅ Value is a PlainObject with typescript autocompletion
// Note that there's no runtime checking of keys, so they are
// `unknown | undefined`. They will require unsing `?.` to access.
const url = value?.data?.attributes?.url; // autocompletion works
// ✅ url is `unknown | undefined`, so in order to use it, you'll need to
// manually check for the type.
if (typeof url === 'string') {
console.log(url.toUpperCase());
}
}
PlainObject
import { assertPlainObject } from '@httpx/plain-object';
import type { PlainObject } from '@httpx/plain-object';
function someFn(value: PlainObject) {
//
}
const value = { key: 'value' } as unknown;
assertPlainObject(value);
someFn(value)
Benchmarks
Performance is continuously monitored thanks to codspeed.io.
RUN v2.0.5 /home/sebastien/github/httpx/packages/plain-object
✓ bench/comparative.bench.ts (6) 4778ms
✓ Compare calling isPlainObject with 100x mixed types values (6) 4779ms
name hz min max mean p75 p99 p995 p999 rme samples
· @httpx/plain-object: `isPlainObject(v)` 1,494,047.57 0.0005 8.3748 0.0007 0.0007 0.0008 0.0009 0.0047 ±3.40% 747024 fastest
· (sindresorhus/)is-plain-obj: `isPlainObj(v)` 1,314,933.16 0.0005 11.7854 0.0008 0.0007 0.0014 0.0015 0.0022 ±6.83% 657467
· @sindresorhus/is: `is.plainObject(v)` 934,442.37 0.0009 2.1268 0.0011 0.0011 0.0015 0.0018 0.0065 ±1.38% 467222
· estoolkit: `isPlainObject(v)` 378,403.92 0.0020 10.3395 0.0026 0.0026 0.0035 0.0055 0.0155 ±4.23% 189202
· (jonschlinkert/)is-plain-object: `isPlainObject(v)` 629,387.99 0.0012 13.2170 0.0016 0.0015 0.0023 0.0030 0.0129 ±6.81% 314694
· lodash-es: `_.isPlainObject(v)` 21,164.79 0.0361 11.2577 0.0472 0.0446 0.1057 0.1678 0.5020 ±5.03% 10583 slowest
BENCH Summary
@httpx/plain-object: `isPlainObject(v)` - bench/comparative.bench.ts > Compare calling isPlainObject with 100x mixed types values
1.14x faster than (sindresorhus/)is-plain-obj: `isPlainObj(v)`
1.60x faster than @sindresorhus/is: `is.plainObject(v)`
2.37x faster than (jonschlinkert/)is-plain-object: `isPlainObject(v)`
3.95x faster than estoolkit: `isPlainObject(v)`
70.59x faster than lodash-es: `_.isPlainObject(v)`
See benchmark file for details.
Bundle size
Bundle size is tracked by a size-limit configuration
Scenario (esm) | Size (compressed) |
---|---|
import { isPlainObject } from '@httpx/plain-object | ~ 100B |
import { assertPlainObject } from '@httpx/plain-object | ~ 160B |
isPlainObject + assertPlainObject | ~ 170B |
For CJS usage (not recommended) track the size on bundlephobia.
Compatibility
Level | CI | Description |
---|---|---|
Node | ✅ | CI for 18.x, 20.x & 22.x. |
Browsers | ✅ | > 96% on 07/2024. Mins to Chrome 96+, Firefox 90+, Edge 19+, iOS 12+, Safari 12+, Opera 77+ |
Edge | ✅ | Ensured on CI with @vercel/edge-runtime. |
Typescript | ✅ | TS 5.0 + / are-the-type-wrong checks on CI. |
ES2022 | ✅ | Dist files checked with es-check |
Performance | ✅ | Monitored with codspeed.io |
For older browsers: most frontend frameworks can transpile the library (ie: nextjs…)
Credits
This library wouldn’t be possible without @sindresorhus is-plain-obj. It passes the same test suite and should be 100% compatible with it. Notable differences:
- Slighly smaller bundle and performance.
- Named export.
- Provide a
PlainObject
type andassertPlainObject
function. - Typescript convenience
PlainObject
type. - ESM and CJS formats.