diff --git a/.changeset/chilly-icons-guess.md b/.changeset/chilly-icons-guess.md new file mode 100644 index 00000000000..edabd1cb649 --- /dev/null +++ b/.changeset/chilly-icons-guess.md @@ -0,0 +1,11 @@ +--- +'@graphql-tools/utils': patch +--- + +Fix the bug in `mergeDeep`; + +The following inputs and outputs are corrected; + +- `mergeDeep([{a:2}, undefined])` - Any nullish values should be ignored so it should return `{a:2}` +- `mergeDeep([])` - no sources should return `undefined` +- `mergeDeep([undefined])` - no sources should return `undefined` diff --git a/packages/utils/src/mergeDeep.ts b/packages/utils/src/mergeDeep.ts index 9f690e8c9c9..3a063fc351b 100644 --- a/packages/utils/src/mergeDeep.ts +++ b/packages/utils/src/mergeDeep.ts @@ -12,6 +12,12 @@ export function mergeDeep( respectArrays = false, respectArrayLength = false, ): UnboxIntersection>> & any { + if (sources.length === 0) { + return; + } + if (sources.length === 1) { + return sources[0]; + } let expectedLength: number | undefined; let allArrays = true; const areArraysInTheSameLength = sources.every(source => { @@ -46,14 +52,17 @@ export function mergeDeep( let firstObjectSource: any; if (respectPrototype) { firstObjectSource = sources.find(source => isObject(source)); - if (output == null) { - output = {}; - } if (firstObjectSource) { + if (output == null) { + output = {}; + } Object.setPrototypeOf(output, Object.create(Object.getPrototypeOf(firstObjectSource))); } } for (const source of sources) { + if (source == null) { + continue; + } if (isObject(source)) { if (firstObjectSource) { const outputPrototype = Object.getPrototypeOf(output); diff --git a/packages/utils/tests/mergeDeep.test.ts b/packages/utils/tests/mergeDeep.test.ts index 7391f17b332..228c506e578 100644 --- a/packages/utils/tests/mergeDeep.test.ts +++ b/packages/utils/tests/mergeDeep.test.ts @@ -72,4 +72,16 @@ describe('mergeDeep', () => { const b = { options: ['$A', '$B'] }; expect(mergeDeep([a, b], undefined, true, true)).toEqual({ options: ['$A', '$B'] }); }); + + it('filters nullish values', () => { + expect(mergeDeep([{ a: 'dsa' }, { a: 'dd', b: 1 }, undefined])).toEqual({ a: 'dd', b: 1 }); + }); + + it('respects empty objects', () => { + expect(mergeDeep([{}])).toEqual({}); + }); + + it('returns undefined when an empty sources array passed', () => { + expect(mergeDeep([])).toEqual(undefined); + }); });