=== tests/cases/conformance/functions/functionImplementations.ts === // FunctionExpression with no return type annotation and no return statement returns void var v: void = function () { } (); >v : void >function () { } () : void >function () { } : () => void // FunctionExpression f with no return type annotation and directly references f in its body returns any var a: any = function f() { >a : any >function f() { return f;} : () => any >f : () => any return f; >f : () => any }; var a: any = function f() { >a : any >function f() { return f();} : () => any >f : () => any return f(); >f() : any >f : () => any }; // FunctionExpression f with no return type annotation and indirectly references f in its body returns any var a: any = function f() { >a : any >function f() { var x = f; return x;} : () => any >f : () => any var x = f; >x : () => any >f : () => any return x; >x : () => any }; // Two mutually recursive function implementations with no return type annotations function rec1() { >rec1 : () => any return rec2(); >rec2() : any >rec2 : () => any } function rec2() { >rec2 : () => any return rec1(); >rec1() : any >rec1 : () => any } var a = rec1(); >a : any >rec1() : any >rec1 : () => any var a = rec2(); >a : any >rec2() : any >rec2 : () => any // Two mutually recursive function implementations with return type annotation in one function rec3(): number { >rec3 : () => number return rec4(); >rec4() : number >rec4 : () => number } function rec4() { >rec4 : () => number return rec3(); >rec3() : number >rec3 : () => number } var n: number; >n : number var n = rec3(); >n : number >rec3() : number >rec3 : () => number var n = rec4(); >n : number >rec4() : number >rec4 : () => number // FunctionExpression with no return type annotation and returns a number var n = function () { >n : number >function () { return 3;} () : number >function () { return 3;} : () => number return 3; } (); // FunctionExpression with no return type annotation and returns null var nu = null; >nu : any var nu = function () { >nu : any >function () { return null;} () : any >function () { return null;} : () => any return null; } (); // FunctionExpression with no return type annotation and returns undefined var un = undefined; >un : any >undefined : undefined var un = function () { >un : any >function () { return undefined;} () : any >function () { return undefined;} : () => any return undefined; >undefined : undefined } (); // FunctionExpression with no return type annotation and returns a type parameter type var n = function (x: T) { >n : number >function (x: T) { return x;} (4) : number >function (x: T) { return x;} : (x: T) => T >T : T >x : T >T : T return x; >x : T } (4); // FunctionExpression with no return type annotation and returns a constrained type parameter type var n = function (x: T) { >n : number >function (x: T) { return x;} (4) : number >function (x: T) { return x;} : (x: T) => T >T : T >x : T >T : T return x; >x : T } (4); // FunctionExpression with no return type annotation with multiple return statements with identical types var n = function () { >n : number >function () { return 3; return 5;}() : number >function () { return 3; return 5;} : () => number return 3; return 5; }(); // Otherwise, the inferred return type is the first of the types of the return statement expressions // in the function body that is a supertype of each of the others, // ignoring return statements with no expressions. // A compile - time error occurs if no return statement expression has a type that is a supertype of each of the others. // FunctionExpression with no return type annotation with multiple return statements with subtype relation between returns class Base { private m; } >Base : Base >m : any class Derived extends Base { private q; } >Derived : Derived >Base : Base >q : any var b: Base; >b : Base >Base : Base var b = function () { >b : Base >function () { return new Base(); return new Derived();} () : Base >function () { return new Base(); return new Derived();} : () => Base return new Base(); return new Derived(); >new Base() : Base >Base : typeof Base >new Derived() : Derived >Derived : typeof Derived } (); // FunctionExpression with no return type annotation with multiple return statements with one a recursive call var a = function f() { >a : any >function f() { return new Base(); return new Derived(); return f(); // ?} () : any >function f() { return new Base(); return new Derived(); return f(); // ?} : () => any >f : () => any return new Base(); return new Derived(); return f(); // ? >new Base() : Base >Base : typeof Base >new Derived() : Derived >Derived : typeof Derived >f() : any >f : () => any } (); // FunctionExpression with non -void return type annotation with a single throw statement undefined === function (): number { >undefined === function (): number { throw undefined;} : boolean >undefined : undefined >function (): number { throw undefined;} : () => number throw undefined; >undefined : undefined }; // Type of 'this' in function implementation is 'any' function thisFunc() { >thisFunc : () => void var x = this; >x : any >this : any var x: any; >x : any } // Function signature with optional parameter, no type annotation and initializer has initializer's type function opt1(n = 4) { >opt1 : (n?: number) => void >n : number var m = n; >m : number >n : number var m: number; >m : number } // Function signature with optional parameter, no type annotation and initializer has initializer's widened type function opt2(n = { x: null, y: undefined }) { >opt2 : (n?: { x: any; y: any; }) => void >n : { x: any; y: any; } >{ x: null, y: undefined } : { x: null; y: undefined; } >x : null >y : undefined >undefined : undefined var m = n; >m : { x: any; y: any; } >n : { x: any; y: any; } var m: { x: any; y: any }; >m : { x: any; y: any; } >x : any >y : any } // Function signature with initializer referencing other parameter to the left function opt3(n: number, m = n) { >opt3 : (n: number, m?: number) => void >n : number >m : number >n : number var y = m; >y : number >m : number var y: number; >y : number } // Function signature with optional parameter has correct codegen // (tested above) // FunctionExpression with non -void return type annotation return with no expression function f6(): number { >f6 : () => number return; } class Derived2 extends Base { private r: string; } >Derived2 : Derived2 >Base : Base >r : string class AnotherClass { private x } >AnotherClass : AnotherClass >x : any // if f is a contextually typed function expression, the inferred return type is the union type // of the types of the return statement expressions in the function body, // ignoring return statements with no expressions. var f7: (x: number) => string | number = x => { // should be (x: number) => number | string >f7 : (x: number) => string | number >x : number >x => { // should be (x: number) => number | string if (x < 0) { return x; } return x.toString();} : (x: number) => string | number >x : number if (x < 0) { return x; } >x < 0 : boolean >x : number >x : number return x.toString(); >x.toString() : string >x.toString : (radix?: number) => string >x : number >toString : (radix?: number) => string } var f8: (x: number) => any = x => { // should be (x: number) => Base >f8 : (x: number) => any >x : number >x => { // should be (x: number) => Base return new Base(); return new Derived2();} : (x: number) => Base >x : number return new Base(); >new Base() : Base >Base : typeof Base return new Derived2(); >new Derived2() : Derived2 >Derived2 : typeof Derived2 } var f9: (x: number) => any = x => { // should be (x: number) => Base >f9 : (x: number) => any >x : number >x => { // should be (x: number) => Base return new Base(); return new Derived(); return new Derived2();} : (x: number) => Base >x : number return new Base(); >new Base() : Base >Base : typeof Base return new Derived(); >new Derived() : Derived >Derived : typeof Derived return new Derived2(); >new Derived2() : Derived2 >Derived2 : typeof Derived2 } var f10: (x: number) => any = x => { // should be (x: number) => Derived | Derived1 >f10 : (x: number) => any >x : number >x => { // should be (x: number) => Derived | Derived1 return new Derived(); return new Derived2();} : (x: number) => Derived | Derived2 >x : number return new Derived(); >new Derived() : Derived >Derived : typeof Derived return new Derived2(); >new Derived2() : Derived2 >Derived2 : typeof Derived2 } var f11: (x: number) => any = x => { // should be (x: number) => Base | AnotherClass >f11 : (x: number) => any >x : number >x => { // should be (x: number) => Base | AnotherClass return new Base(); return new AnotherClass();} : (x: number) => Base | AnotherClass >x : number return new Base(); >new Base() : Base >Base : typeof Base return new AnotherClass(); >new AnotherClass() : AnotherClass >AnotherClass : typeof AnotherClass } var f12: (x: number) => any = x => { // should be (x: number) => Base | AnotherClass >f12 : (x: number) => any >x : number >x => { // should be (x: number) => Base | AnotherClass return new Base(); return; // should be ignored return new AnotherClass();} : (x: number) => Base | AnotherClass >x : number return new Base(); >new Base() : Base >Base : typeof Base return; // should be ignored return new AnotherClass(); >new AnotherClass() : AnotherClass >AnotherClass : typeof AnotherClass }