diff --git a/docs/typed/is-object.mdx b/docs/typed/is-object.mdx index 0e746501..1df85ea1 100644 --- a/docs/typed/is-object.mdx +++ b/docs/typed/is-object.mdx @@ -16,3 +16,5 @@ isObject(['hello']) // => false isObject(null) // => false isObject({ say: 'hello' }) // => true ``` + +**Beware:** This function returns `false` for objects created with `Object.create(null)`. diff --git a/src/object/assign.ts b/src/object/assign.ts index 40b7d779..95218bae 100644 --- a/src/object/assign.ts +++ b/src/object/assign.ts @@ -1,4 +1,4 @@ -import { isObject } from 'radashi' +import { isPlainObject } from 'radashi' /** * Merges two objects together recursivly into a new object applying @@ -10,10 +10,13 @@ export const assign = >( override: X ): X => { if (!initial || !override) return initial ?? override ?? {} - const merged = { ...initial } + const proto = Object.getPrototypeOf(initial) + const merged = proto + ? { ...initial } + : Object.assign(Object.create(proto), initial) for (const key in override) { if (Object.prototype.hasOwnProperty.call(override, key)) { - merged[key] = isObject(initial[key]) + merged[key] = isPlainObject(initial[key]) ? assign(initial[key], override[key]) : override[key] } diff --git a/src/object/keys.ts b/src/object/keys.ts index b0791da3..d624179b 100644 --- a/src/object/keys.ts +++ b/src/object/keys.ts @@ -1,5 +1,4 @@ -import { isArray } from 'radashi' -import { isObject } from 'radashi' +import { isArray, isPlainObject } from 'radashi' /** * Get a string list of all key names that exist in an object (deep). @@ -11,7 +10,7 @@ import { isObject } from 'radashi' export const keys = (value: TValue): string[] => { if (!value) return [] const getKeys = (nested: any, paths: string[]): string[] => { - if (isObject(nested)) { + if (isPlainObject(nested)) { return Object.entries(nested).flatMap(([k, v]) => getKeys(v, [...paths, k]) ) diff --git a/src/object/tests/assign.test.ts b/src/object/tests/assign.test.ts index 4f7bcb76..185b623d 100644 --- a/src/object/tests/assign.test.ts +++ b/src/object/tests/assign.test.ts @@ -49,4 +49,13 @@ describe('assign function', () => { const result = _.assign({}, { b: 'y' }) expect(result).toEqual({ b: 'y' }) }) + test('works with Object.create(null)', () => { + const object = { a: Object.create(null) } + object.a.b = 1 + + const result = _.assign(object, { a: { c: 2 } }) + + expect(result).toEqual({ a: { b: 1, c: 2 } }) + expect(Object.getPrototypeOf(result.a)).toBe(null) + }) }) diff --git a/src/object/tests/keys.test.ts b/src/object/tests/keys.test.ts index 1168cedc..68a5d0c6 100644 --- a/src/object/tests/keys.test.ts +++ b/src/object/tests/keys.test.ts @@ -30,4 +30,12 @@ describe('keys function', () => { 'enemies.0.power' ]) }) + test('works with Object.create(null)', () => { + const object = Object.create(null) + object.a = 1 + object.b = [2] + object.c = { d: 3 } + const result = _.keys(object) + expect(result).toEqual(['a', 'b.0', 'c.d']) + }) })