@@ -254,4 +254,135 @@ export class TupleTests {
254254 const result = util . executeLua ( lua ) ;
255255 Expect ( result ) . toBe ( "foobar" ) ;
256256 }
257+
258+ @Test ( "Tuple Return on Type Alias" )
259+ public tupleReturnOnTypeAlias ( ) : void {
260+ const code =
261+ `/** @tupleReturn */ type Fn = () => [number, number];
262+ const fn: Fn = () => [1, 2];
263+ const [a, b] = fn();
264+ return a + b;` ;
265+ const lua = util . transpileString ( code ) ;
266+ Expect ( lua ) . not . toContain ( "unpack" ) ;
267+ const result = util . executeLua ( lua ) ;
268+ Expect ( result ) . toBe ( 3 ) ;
269+ }
270+
271+ @Test ( "Tuple Return on Interface" )
272+ public tupleReturnOnInterface ( ) : void {
273+ const code =
274+ `/** @tupleReturn */ interface Fn { (): [number, number]; }
275+ const fn: Fn = () => [1, 2];
276+ const [a, b] = fn();
277+ return a + b;` ;
278+ const lua = util . transpileString ( code ) ;
279+ Expect ( lua ) . not . toContain ( "unpack" ) ;
280+ const result = util . executeLua ( lua ) ;
281+ Expect ( result ) . toBe ( 3 ) ;
282+ }
283+
284+ @Test ( "Tuple Return on Interface Signature" )
285+ public tupleReturnOnInterfaceSignature ( ) : void {
286+ const code =
287+ `interface Fn {
288+ /** @tupleReturn */ (): [number, number];
289+ }
290+ const fn: Fn = () => [1, 2];
291+ const [a, b] = fn();
292+ return a + b;` ;
293+ const lua = util . transpileString ( code ) ;
294+ Expect ( lua ) . not . toContain ( "unpack" ) ;
295+ const result = util . executeLua ( lua ) ;
296+ Expect ( result ) . toBe ( 3 ) ;
297+ }
298+
299+ @Test ( "Tuple Return on Overload" )
300+ public tupleReturnOnOverload ( ) : void {
301+ const code =
302+ `function fn(a: number): number;
303+ /** @tupleReturn */ function fn(a: string, b: string): [string, string];
304+ function fn(a: number | string, b?: string): number | [string, string] {
305+ if (typeof a === "number") {
306+ return a;
307+ } else {
308+ return [a, b as string];
309+ }
310+ }
311+ const a = fn(3);
312+ const [b, c] = fn("foo", "bar");
313+ return a + b + c` ;
314+ const lua = util . transpileString ( code ) ;
315+ Expect ( lua ) . not . toContain ( "unpack" ) ;
316+ const result = util . executeLua ( lua ) ;
317+ Expect ( result ) . toBe ( "3foobar" ) ;
318+ }
319+
320+ @Test ( "Tuple Return on Interface Overload" )
321+ public tupleReturnOnInterfaceOverload ( ) : void {
322+ const code =
323+ `interface Fn {
324+ (a: number): number;
325+ /** @tupleReturn */ (a: string, b: string): [string, string];
326+ }
327+ const fn = ((a: number | string, b?: string): number | [string, string] => {
328+ if (typeof a === "number") {
329+ return a;
330+ } else {
331+ return [a, b as string];
332+ }
333+ }) as Fn;
334+ const a = fn(3);
335+ const [b, c] = fn("foo", "bar");
336+ return a + b + c` ;
337+ const lua = util . transpileString ( code ) ;
338+ Expect ( lua ) . not . toContain ( "unpack" ) ;
339+ const result = util . executeLua ( lua ) ;
340+ Expect ( result ) . toBe ( "3foobar" ) ;
341+ }
342+
343+ @Test ( "Tuple Return on Interface Method Overload" )
344+ public tupleReturnOnInterfaceMethodOverload ( ) : void {
345+ const code =
346+ `interface Foo {
347+ foo(a: number): number;
348+ /** @tupleReturn */ foo(a: string, b: string): [string, string];
349+ }
350+ const bar = ({
351+ foo: (a: number | string, b?: string): number | [string, string] => {
352+ if (typeof a === "number") {
353+ return a;
354+ } else {
355+ return [a, b as string];
356+ }
357+ }
358+ }) as Foo;
359+ const a = bar.foo(3);
360+ const [b, c] = bar.foo("foo", "bar");
361+ return a + b + c` ;
362+ const lua = util . transpileString ( code ) ;
363+ Expect ( lua ) . not . toContain ( "unpack" ) ;
364+ const result = util . executeLua ( lua ) ;
365+ Expect ( result ) . toBe ( "3foobar" ) ;
366+ }
367+
368+ @Test ( "Tuple Return vs Non-Tuple Return Overload" )
369+ public tupleReturnVsNonTupleReturnOverload ( ) : void {
370+ const luaHeader =
371+ `function fn(a, b)
372+ if type(a) == "number" then
373+ return {a, a + 1}
374+ else
375+ return a, b
376+ end
377+ end` ;
378+ const tsHeader =
379+ `declare function fn(this: void, a: number): [number, number];
380+ /** @tupleReturn */ declare function fn(this: void, a: string, b: string): [string, string];` ;
381+ const code =
382+ `const [a, b] = fn(3);
383+ const [c, d] = fn("foo", "bar");
384+ return (a + b) + c + d;` ;
385+ const result = util . transpileAndExecute ( code , undefined , luaHeader , tsHeader ) ;
386+ Expect ( result ) . toBe ( "7foobar" ) ;
387+ }
257388}
0 commit comments