diff --git a/src/lualib/ArrayFlat.ts b/src/lualib/ArrayFlat.ts index 4006b51d5..54120e69a 100644 --- a/src/lualib/ArrayFlat.ts +++ b/src/lualib/ArrayFlat.ts @@ -1,7 +1,13 @@ function __TS__ArrayFlat(this: void, array: any[], depth = 1): any[] { let result: any[] = []; for (const value of array) { - if (depth > 0 && type(value) === "table" && 1 in value) { + if ( + depth > 0 && + type(value) === "table" && + // Workaround to determine if value is an array or not (fails in case of objects without keys) + // See discussion in: https://github.com/TypeScriptToLua/TypeScriptToLua/pull/737 + (1 in value || (next as NextEmptyCheck)(value, undefined) === undefined) + ) { result = result.concat(__TS__ArrayFlat(value, depth - 1)); } else { result[result.length] = value; diff --git a/src/lualib/ArrayFlatMap.ts b/src/lualib/ArrayFlatMap.ts index 7bd7a8a22..02d58329b 100644 --- a/src/lualib/ArrayFlatMap.ts +++ b/src/lualib/ArrayFlatMap.ts @@ -6,7 +6,12 @@ function __TS__ArrayFlatMap( let result: U[] = []; for (let i = 0; i < array.length; i++) { const value = callback(array[i], i, array); - if (type(value) === "table" && 1 in value) { + if ( + type(value) === "table" && + // Workaround to determine if value is an array or not (fails in case of objects without keys) + // See discussion in: https://github.com/TypeScriptToLua/TypeScriptToLua/pull/737 + (1 in value || (next as NextEmptyCheck)(value as any, undefined) === undefined) + ) { result = result.concat(value); } else { result[result.length] = value as U; diff --git a/src/lualib/declarations/global.d.ts b/src/lualib/declarations/global.d.ts index 77a88b694..4a86d2542 100644 --- a/src/lualib/declarations/global.d.ts +++ b/src/lualib/declarations/global.d.ts @@ -5,6 +5,9 @@ declare var __TS__originalTraceback: | ((this: void, thread?: any, message?: string, level?: number) => string) | undefined; +// Override next declaration so we can omit extra return values +declare type NextEmptyCheck = (this: void, table: any, index: undefined) => unknown | undefined; + declare function tonumber(value: any, base?: number): number | undefined; declare function type( value: any diff --git a/test/unit/builtins/array.spec.ts b/test/unit/builtins/array.spec.ts index 51aac9cc3..56d144e02 100644 --- a/test/unit/builtins/array.spec.ts +++ b/test/unit/builtins/array.spec.ts @@ -487,6 +487,8 @@ test.each([ }); test.each([ + { array: [[]], expected: [] }, + { array: [{ a: 1 }, { a: 2 }, { a: 3 }], expected: [{ a: 1 }, { a: 2 }, { a: 3 }] }, { array: [1, [2, 3], 4], expected: [1, 2, 3, 4] }, { array: [1, [2, 3], 4], depth: 0, expected: [1, [2, 3], 4] }, { array: [1, [[2], [3]], 4], expected: [1, [2], [3], 4] }, @@ -497,6 +499,8 @@ test.each([ }); test.each([ + { array: [[]], map: (v: T) => v, expected: [] }, + { array: [1, 2, 3], map: (v: number) => ({ a: v * 2 }), expected: [{ a: 2 }, { a: 4 }, { a: 6 }] }, { array: [1, [2, 3], [4]], map: (value: T) => value, expected: [1, 2, 3, 4] }, { array: [1, 2, 3], map: (v: number) => v * 2, expected: [2, 4, 6] }, { array: [1, 2, 3], map: (v: number) => [v, v * 2], expected: [1, 2, 2, 4, 3, 6] },