@@ -263,6 +263,7 @@ export class AssignmentTests {
263263 @TestCase ( "foo.voidLambdaProp" , "Foo.staticMethod" , "foo+staticMethod" )
264264 @TestCase ( "foo.voidLambdaProp" , "Foo.staticLambdaProp" , "foo+staticLambdaProp" )
265265 @TestCase ( "foo.voidLambdaProp" , "foo.voidMethod" , "foo+voidMethod" )
266+ @TestCase ( "func" , "(func as (string | ((s: string) => string)))" , "foo+func" )
266267 @Test ( "Valid function assignment" )
267268 public validFunctionAssignment ( func : string , assignTo : string , expectResult : string ) : void {
268269 const code = `${ AssignmentTests . funcAssignTestCode } ${ func } = ${ assignTo } ; return ${ func } ("foo");` ;
@@ -279,10 +280,17 @@ export class AssignmentTests {
279280 @TestCase ( "s => s" , "foo" )
280281 @TestCase ( "function(s) { return s; }" , "foo" )
281282 @TestCase ( "function(this: void, s: string) { return s; }" , "foo" )
283+ @TestCase ( "func" , "foo+func" , "string | ((s: string) => string)" )
284+ @TestCase ( "func" , "foo+func" , "T" )
282285 @Test ( "Valid function argument" )
283- public validFunctionArgument ( func : string , expectResult : string ) : void {
286+ public validFunctionArgument ( func : string , expectResult : string , funcType ?: string ) : void {
287+ if ( ! funcType ) {
288+ funcType = "(s: string) => s" ;
289+ }
284290 const code = `${ AssignmentTests . funcAssignTestCode }
285- function takesFunc(fn: (s: string) => s) { return fn("foo"); }
291+ function takesFunc<T extends ((s: string) => string)>(fn: ${ funcType } ) {
292+ return (fn as any)("foo");
293+ }
286294 return takesFunc(${ func } );` ;
287295 const result = util . transpileAndExecute ( code ) ;
288296 Expect ( result ) . toBe ( expectResult ) ;
@@ -297,10 +305,17 @@ export class AssignmentTests {
297305 @TestCase ( "s => s" , "foo" )
298306 @TestCase ( "function(s) { return s; }" , "foo" )
299307 @TestCase ( "function(this: void, s: string) { return s; }" , "foo" )
308+ @TestCase ( "func" , "foo+func" , "string | ((s: string) => string)" )
309+ @TestCase ( "func" , "foo+func" , "T" )
300310 @Test ( "Valid function return" )
301- public validFunctionReturn ( func : string , expectResult : string ) : void {
311+ public validFunctionReturn ( func : string , expectResult : string , funcType ?: string ) : void {
312+ if ( ! funcType ) {
313+ funcType = "(s: string) => s" ;
314+ }
302315 const code = `${ AssignmentTests . funcAssignTestCode }
303- function returnsFunc(): (s: string) => string { return ${ func } ; }
316+ function returnsFunc<T extends ((s: string) => string)>(): ${ funcType } {
317+ return ${ func } ;
318+ }
304319 const fn = returnsFunc();
305320 return fn("foo");` ;
306321 const result = util . transpileAndExecute ( code ) ;
@@ -367,6 +382,7 @@ export class AssignmentTests {
367382 @TestCase ( "thisLambda" , "Foo.thisStaticMethod" , "foo+thisStaticMethod" )
368383 @TestCase ( "thisLambda" , "Foo.thisStaticLambdaProp" , "foo+thisStaticLambdaProp" )
369384 @TestCase ( "thisLambda" , "thisFunc" , "foo+thisFunc" )
385+ @TestCase ( "foo.method" , "(foo.method as (string | ((this: Foo, s: string) => string))" , "foo+method" )
370386 @Test ( "Valid method assignment" )
371387 public validMethodAssignment ( func : string , assignTo : string , expectResult : string ) : void {
372388 const code = `${ AssignmentTests . funcAssignTestCode } ${ func } = ${ assignTo } ; return ${ func } ("foo");` ;
@@ -383,10 +399,17 @@ export class AssignmentTests {
383399 @TestCase ( "s => s" , "foo" )
384400 @TestCase ( "function(s) { return s; }" , "foo" )
385401 @TestCase ( "function(this: Foo, s: string) { return s; }" , "foo" )
402+ @TestCase ( "foo.method" , "foo+method" , "string | ((this: Foo, s: string) => string)" )
403+ @TestCase ( "foo.method" , "foo+method" , "T" )
386404 @Test ( "Valid method argument" )
387- public validMethodArgument ( func : string , expectResult : string ) : void {
405+ public validMethodArgument ( func : string , expectResult : string , funcType ?: string ) : void {
406+ if ( ! funcType ) {
407+ funcType = "(this: Foo, s: string) => string" ;
408+ }
388409 const code = `${ AssignmentTests . funcAssignTestCode }
389- function takesMethod(meth: (this: Foo, s: string) => string) { foo.method = meth; }
410+ function takesMethod<T extends ((this: Foo, s: string) => string)>(meth: ${ funcType } ) {
411+ foo.method = meth as any;
412+ }
390413 takesMethod(${ func } );
391414 return foo.method("foo");` ;
392415 const result = util . transpileAndExecute ( code ) ;
@@ -402,10 +425,17 @@ export class AssignmentTests {
402425 @TestCase ( "s => s" , "foo" )
403426 @TestCase ( "function(s) { return s; }" , "foo" )
404427 @TestCase ( "function(this: Foo, s: string) { return s; }" , "foo" )
428+ @TestCase ( "foo.method" , "foo+method" , "string | ((this: Foo, s: string) => string)" )
429+ @TestCase ( "foo.method" , "foo+method" , "T" )
405430 @Test ( "Valid method return" )
406- public validMethodReturn ( func : string , expectResult : string ) : void {
431+ public validMethodReturn ( func : string , expectResult : string , funcType ?: string ) : void {
432+ if ( ! funcType ) {
433+ funcType = "(this: Foo, s: string) => string" ;
434+ }
407435 const code = `${ AssignmentTests . funcAssignTestCode }
408- function returnMethod(): (this: Foo, s: string) => string { return ${ func } ; }
436+ function returnMethod<T extends ((this: Foo, s: string) => string)>(): ${ funcType } {
437+ return ${ func } ;
438+ }
409439 foo.method = returnMethod();
410440 return foo.method("foo");` ;
411441 const result = util . transpileAndExecute ( code ) ;
@@ -442,6 +472,7 @@ export class AssignmentTests {
442472 @TestCase ( "Foo.staticLambdaProp" , "Foo.thisStaticMethod" )
443473 @TestCase ( "Foo.staticLambdaProp" , "Foo.thisStaticLambdaProp" )
444474 @TestCase ( "Foo.staticLambdaProp" , "function(this: Foo, s: string) { return s; }" )
475+ @TestCase ( "func" , "(foo.method as (string | ((this: Foo, s: string) => string)))" )
445476 @Test ( "Invalid function assignment" )
446477 public invalidFunctionAssignment ( func : string , assignTo : string ) : void {
447478 const code = `${ AssignmentTests . funcAssignTestCode } ${ func } = ${ assignTo } ;` ;
@@ -457,10 +488,15 @@ export class AssignmentTests {
457488 @TestCase ( "thisFunc" )
458489 @TestCase ( "thisLambda" )
459490 @TestCase ( "function(this: Foo, s: string) { return s; }" )
491+ @TestCase ( "foo.method" , "string | ((s: string) => string)" )
492+ @TestCase ( "foo.method" , "T" )
460493 @Test ( "Invalid function argument" )
461- public invalidFunctionArgument ( func : string ) : void {
494+ public invalidFunctionArgument ( func : string , funcType ?: string ) : void {
495+ if ( ! funcType ) {
496+ funcType = "(s: string) => s" ;
497+ }
462498 const code = `${ AssignmentTests . funcAssignTestCode }
463- declare function takesFunc(fn: ( s: string) => s );
499+ declare function takesFunc<T extends (( s: string) => string)>(fn: ${ funcType } );
464500 takesFunc(${ func } );` ;
465501 Expect ( ( ) => util . transpileString ( code ) ) . toThrowError (
466502 TranspileError ,
@@ -474,10 +510,17 @@ export class AssignmentTests {
474510 @TestCase ( "thisFunc" )
475511 @TestCase ( "thisLambda" )
476512 @TestCase ( "function(this: Foo, s: string) { return s; }" )
513+ @TestCase ( "foo.method" , "string | ((s: string) => string)" )
514+ @TestCase ( "foo.method" , "T" )
477515 @Test ( "Invalid function return" )
478- public invalidFunctionReturn ( func : string ) : void {
516+ public invalidFunctionReturn ( func : string , funcType ?: string ) : void {
517+ if ( ! funcType ) {
518+ funcType = "(s: string) => s" ;
519+ }
479520 const code = `${ AssignmentTests . funcAssignTestCode }
480- function returnsFunc(): (s: string) => string { return ${ func } ; }` ;
521+ function returnsFunc<T extends ((s: string) => string)>(): ${ funcType } {
522+ return ${ func } ;
523+ }` ;
481524 Expect ( ( ) => util . transpileString ( code ) ) . toThrowError (
482525 TranspileError ,
483526 "Unsupported conversion from method to function. To fix, wrap the method in an arrow function." ) ;
@@ -525,6 +568,7 @@ export class AssignmentTests {
525568 @TestCase ( "thisLambda" , "foo.voidMethod" )
526569 @TestCase ( "thisLambda" , "foo.voidLambdaProp" )
527570 @TestCase ( "thisLambda" , "function(this: void, s: string) { return s; }" )
571+ @TestCase ( "foo.method" , "(func as string | ((s: string) => string))" )
528572 @Test ( "Invalid method assignment" )
529573 public invalidMethodAssignment ( func : string , assignTo : string ) : void {
530574 const code = `${ AssignmentTests . funcAssignTestCode } ${ func } = ${ assignTo } ;` ;
@@ -541,10 +585,15 @@ export class AssignmentTests {
541585 @TestCase ( "foo.voidMethod" )
542586 @TestCase ( "foo.voidLambdaProp" )
543587 @TestCase ( "function(this: void, s: string) { return s; }" )
588+ @TestCase ( "func" , "string | ((this: Foo, s: string) => string)" )
589+ @TestCase ( "func" , "T" )
544590 @Test ( "Invalid method argument" )
545- public invalidMethodArgument ( func : string ) : void {
591+ public invalidMethodArgument ( func : string , funcType ?: string ) : void {
592+ if ( ! funcType ) {
593+ funcType = "(this: Foo, s: string) => string" ;
594+ }
546595 const code = `${ AssignmentTests . funcAssignTestCode }
547- declare function takesMethod(meth: ( this: Foo, s: string) => s );
596+ declare function takesMethod<T extends (( this: Foo, s: string) => string)>(meth: ${ funcType } );
548597 takesMethod(${ func } );` ;
549598 Expect ( ( ) => util . transpileString ( code ) ) . toThrowError (
550599 TranspileError ,
@@ -559,10 +608,17 @@ export class AssignmentTests {
559608 @TestCase ( "foo.voidMethod" )
560609 @TestCase ( "foo.voidLambdaProp" )
561610 @TestCase ( "function(this: void, s: string) { return s; }" )
611+ @TestCase ( "func" , "string | ((this: Foo, s: string) => string)" )
612+ @TestCase ( "func" , "T" )
562613 @Test ( "Invalid method return" )
563- public invalidMethodReturn ( func : string ) : void {
614+ public invalidMethodReturn ( func : string , funcType ?: string ) : void {
615+ if ( ! funcType ) {
616+ funcType = "(this: Foo, s: string) => string" ;
617+ }
564618 const code = `${ AssignmentTests . funcAssignTestCode }
565- function returnsMethod(): (this: Foo, s: string) => s { return ${ func } ; }` ;
619+ function returnsMethod<T extends ((this: Foo, s: string) => string)>(): ${ funcType } {
620+ return ${ func } ;
621+ }` ;
566622 Expect ( ( ) => util . transpileString ( code ) ) . toThrowError (
567623 TranspileError ,
568624 "Unsupported conversion from function to method. To fix, wrap the function in an arrow function "
@@ -635,7 +691,7 @@ export class AssignmentTests {
635691 public validInterfaceMethodAssignment ( ) : void {
636692 const code = `interface A { fn(this: void, s: string): string; }
637693 interface B { fn(this: void, s: string): string; }
638- const a: A = { fn: s => s };
694+ const a: A = { fn(this: void, s) { return s; } };
639695 const b: B = a;
640696 return b.fn("foo");` ;
641697 const result = util . transpileAndExecute ( code ) ;
0 commit comments