diff --git a/src/utils.ts b/src/utils.ts index 5bf48d04..119c6b23 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -21,6 +21,21 @@ type ExtractErrAsyncTypes[]> = [idx in keyof T]: T[idx] extends ResultAsync ? E : never } + +const appendValueToEndOfList = (value: T) => (list: T[]): T[] => { + // need to wrap `value` inside of an array in order to prevent + // Array.prototype.concat from destructuring the contents of `value` + // into `list`. + // + // Otherwise you will receive [ 'hi', 1, 2, 3 ] + // when you actually expected a tuple containing [ 'hi', [ 1, 2, 3 ] ] + if (Array.isArray(value)) { + return list.concat([ value ]) + } + + return list.concat(value) +} + /** * Short circuits on the FIRST Err value that we find */ @@ -30,7 +45,7 @@ const combineResultList = (resultList: Result[]): Result => acc.isOk() ? result.isErr() ? err(result.error) - : acc.map((values) => values.concat(result.value)) + : acc.map(appendValueToEndOfList(result.value)) : acc, ok([]) as Result, ) diff --git a/tests/index.test.ts b/tests/index.test.ts index e7643192..d3a24fe2 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -393,6 +393,24 @@ describe('Utils', () => { expect(result._unsafeUnwrap()).toEqual(['Yooooo', 123, true]) }) + + it('Does not destructure / concatenate arrays', () => { + type HomogenousList = [ + Result, + Result, + ] + + const homogenousList: HomogenousList = [ + ok(['hello', 'world']), + ok([1, 2, 3]) + ] + + type ExpectedResult = Result<[ string[], number[] ], boolean | string> + + const result: ExpectedResult = combine(homogenousList) + + expect(result._unsafeUnwrap()).toEqual([ [ 'hello', 'world' ], [ 1, 2, 3 ]]) + }) }) describe('Async `combine`', () => { @@ -424,19 +442,25 @@ describe('Utils', () => { }) it('Combines heterogeneous lists', async () => { - type HeterogenousList = [ ResultAsync, ResultAsync, ResultAsync ] + type HeterogenousList = [ + ResultAsync, + ResultAsync, + ResultAsync, + ResultAsync, + ] const heterogenousList: HeterogenousList = [ okAsync('Yooooo'), okAsync(123), okAsync(true), + okAsync([ 1, 2, 3]), ] - type ExpecteResult = Result<[ string, number, boolean ], string | number | boolean> + type ExpecteResult = Result<[ string, number, boolean, number[] ], string | number | boolean> - const result: ExpecteResult= await combine(heterogenousList) + const result: ExpecteResult = await combine(heterogenousList) - expect(result._unsafeUnwrap()).toEqual(['Yooooo', 123, true]) + expect(result._unsafeUnwrap()).toEqual(['Yooooo', 123, true, [ 1, 2, 3 ]]) }) }) })