diff --git a/tests/baselines/reference/functionImplementationErrors.errors.txt b/tests/baselines/reference/functionImplementationErrors.errors.txt index fbae17a609d..8ebd5aa272d 100644 --- a/tests/baselines/reference/functionImplementationErrors.errors.txt +++ b/tests/baselines/reference/functionImplementationErrors.errors.txt @@ -6,9 +6,15 @@ tests/cases/conformance/functions/functionImplementationErrors.ts(25,16): error tests/cases/conformance/functions/functionImplementationErrors.ts(30,17): error TS2373: Initializer of parameter 'n' cannot reference identifier 'm' declared after it. tests/cases/conformance/functions/functionImplementationErrors.ts(35,17): error TS2373: Initializer of parameter 'n' cannot reference identifier 'm' declared after it. tests/cases/conformance/functions/functionImplementationErrors.ts(40,28): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. +tests/cases/conformance/functions/functionImplementationErrors.ts(49,1): error TS2354: No best common type exists among return expressions. +tests/cases/conformance/functions/functionImplementationErrors.ts(53,10): error TS2354: No best common type exists among return expressions. +tests/cases/conformance/functions/functionImplementationErrors.ts(57,11): error TS2354: No best common type exists among return expressions. +tests/cases/conformance/functions/functionImplementationErrors.ts(61,1): error TS2354: No best common type exists among return expressions. +tests/cases/conformance/functions/functionImplementationErrors.ts(65,11): error TS2354: No best common type exists among return expressions. +tests/cases/conformance/functions/functionImplementationErrors.ts(69,11): error TS2354: No best common type exists among return expressions. -==== tests/cases/conformance/functions/functionImplementationErrors.ts (8 errors) ==== +==== tests/cases/conformance/functions/functionImplementationErrors.ts (14 errors) ==== // FunctionExpression with no return type annotation with multiple return statements with unrelated types var f1 = function () { ~~~~~~~~~~~~~ @@ -83,4 +89,63 @@ tests/cases/conformance/functions/functionImplementationErrors.ts(40,28): error throw undefined; var x = 4; }; + + class Base { private x; } + class AnotherClass { private y; } + class Derived1 extends Base { private m; } + class Derived2 extends Base { private n; } + function f8() { + ~~~~~~~~~~~~~~~ + return new Derived1(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + return new Derived2(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + ~ +!!! error TS2354: No best common type exists among return expressions. + var f9 = function () { + ~~~~~~~~~~~~~ + return new Derived1(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + return new Derived2(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + }; + ~ +!!! error TS2354: No best common type exists among return expressions. + var f10 = () => { + ~~~~~~~ + return new Derived1(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + return new Derived2(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + }; + ~ +!!! error TS2354: No best common type exists among return expressions. + function f11() { + ~~~~~~~~~~~~~~~~ + return new Base(); + ~~~~~~~~~~~~~~~~~~~~~~ + return new AnotherClass(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + ~ +!!! error TS2354: No best common type exists among return expressions. + var f12 = function () { + ~~~~~~~~~~~~~ + return new Base(); + ~~~~~~~~~~~~~~~~~~~~~~ + return new AnotherClass(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + }; + ~ +!!! error TS2354: No best common type exists among return expressions. + var f13 = () => { + ~~~~~~~ + return new Base(); + ~~~~~~~~~~~~~~~~~~~~~~ + return new AnotherClass(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + }; + ~ +!!! error TS2354: No best common type exists among return expressions. \ No newline at end of file diff --git a/tests/baselines/reference/functionImplementationErrors.js b/tests/baselines/reference/functionImplementationErrors.js index 90e1997f396..5eaf9027335 100644 --- a/tests/baselines/reference/functionImplementationErrors.js +++ b/tests/baselines/reference/functionImplementationErrors.js @@ -42,9 +42,44 @@ undefined === function (): number { throw undefined; var x = 4; }; + +class Base { private x; } +class AnotherClass { private y; } +class Derived1 extends Base { private m; } +class Derived2 extends Base { private n; } +function f8() { + return new Derived1(); + return new Derived2(); +} +var f9 = function () { + return new Derived1(); + return new Derived2(); +}; +var f10 = () => { + return new Derived1(); + return new Derived2(); +}; +function f11() { + return new Base(); + return new AnotherClass(); +} +var f12 = function () { + return new Base(); + return new AnotherClass(); +}; +var f13 = () => { + return new Base(); + return new AnotherClass(); +}; //// [functionImplementationErrors.js] +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; // FunctionExpression with no return type annotation with multiple return statements with unrelated types var f1 = function () { return ''; @@ -86,3 +121,51 @@ undefined === function () { throw undefined; var x = 4; }; +var Base = (function () { + function Base() { + } + return Base; +})(); +var AnotherClass = (function () { + function AnotherClass() { + } + return AnotherClass; +})(); +var Derived1 = (function (_super) { + __extends(Derived1, _super); + function Derived1() { + _super.apply(this, arguments); + } + return Derived1; +})(Base); +var Derived2 = (function (_super) { + __extends(Derived2, _super); + function Derived2() { + _super.apply(this, arguments); + } + return Derived2; +})(Base); +function f8() { + return new Derived1(); + return new Derived2(); +} +var f9 = function () { + return new Derived1(); + return new Derived2(); +}; +var f10 = function () { + return new Derived1(); + return new Derived2(); +}; +function f11() { + return new Base(); + return new AnotherClass(); +} +var f12 = function () { + return new Base(); + return new AnotherClass(); +}; +var f13 = function () { + return new Base(); + return new AnotherClass(); +}; diff --git a/tests/baselines/reference/functionImplementations.js b/tests/baselines/reference/functionImplementations.js index 365ee1d7c0d..7c7b753a880 100644 --- a/tests/baselines/reference/functionImplementations.js +++ b/tests/baselines/reference/functionImplementations.js @@ -70,6 +70,10 @@ var n = function () { 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; } class Derived extends Base { private q; } @@ -120,9 +124,37 @@ function f6(): number { return; } - - - +class Derived2 extends Base { private r: string; } +class AnotherClass { private x } +// 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 + if (x < 0) { return x; } + return x.toString(); +} +var f8: (x: number) => any = x => { // should be (x: number) => Base + return new Base(); + return new Derived2(); +} +var f9: (x: number) => any = x => { // should be (x: number) => Base + return new Base(); + return new Derived(); + return new Derived2(); +} +var f10: (x: number) => any = x => { // should be (x: number) => Derived | Derived1 + return new Derived(); + return new Derived2(); +} +var f11: (x: number) => any = x => { // should be (x: number) => Base | AnotherClass + return new Base(); + return new AnotherClass(); +} +var f12: (x: number) => any = x => { // should be (x: number) => Base | AnotherClass + return new Base(); + return; // should be ignored + return new AnotherClass(); +} //// [functionImplementations.js] var __extends = this.__extends || function (d, b) { @@ -192,6 +224,10 @@ var n = function () { 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 var Base = (function () { function Base() { @@ -249,3 +285,46 @@ function opt3(n, m) { function f6() { return; } +var Derived2 = (function (_super) { + __extends(Derived2, _super); + function Derived2() { + _super.apply(this, arguments); + } + return Derived2; +})(Base); +var AnotherClass = (function () { + function AnotherClass() { + } + return AnotherClass; +})(); +// 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 = function (x) { + if (x < 0) { + return x; + } + return x.toString(); +}; +var f8 = function (x) { + return new Base(); + return new Derived2(); +}; +var f9 = function (x) { + return new Base(); + return new Derived(); + return new Derived2(); +}; +var f10 = function (x) { + return new Derived(); + return new Derived2(); +}; +var f11 = function (x) { + return new Base(); + return new AnotherClass(); +}; +var f12 = function (x) { + return new Base(); + return; // should be ignored + return new AnotherClass(); +}; diff --git a/tests/baselines/reference/functionImplementations.types b/tests/baselines/reference/functionImplementations.types index 29fe7c0e39c..04144e3a65b 100644 --- a/tests/baselines/reference/functionImplementations.types +++ b/tests/baselines/reference/functionImplementations.types @@ -168,6 +168,10 @@ var n = function () { 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 @@ -292,6 +296,107 @@ function 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 +} diff --git a/tests/cases/conformance/functions/functionImplementationErrors.ts b/tests/cases/conformance/functions/functionImplementationErrors.ts index 6db4f6ed7e1..ddd3ba0a2c1 100644 --- a/tests/cases/conformance/functions/functionImplementationErrors.ts +++ b/tests/cases/conformance/functions/functionImplementationErrors.ts @@ -41,3 +41,32 @@ undefined === function (): number { throw undefined; var x = 4; }; + +class Base { private x; } +class AnotherClass { private y; } +class Derived1 extends Base { private m; } +class Derived2 extends Base { private n; } +function f8() { + return new Derived1(); + return new Derived2(); +} +var f9 = function () { + return new Derived1(); + return new Derived2(); +}; +var f10 = () => { + return new Derived1(); + return new Derived2(); +}; +function f11() { + return new Base(); + return new AnotherClass(); +} +var f12 = function () { + return new Base(); + return new AnotherClass(); +}; +var f13 = () => { + return new Base(); + return new AnotherClass(); +}; diff --git a/tests/cases/conformance/functions/functionImplementations.ts b/tests/cases/conformance/functions/functionImplementations.ts index d49b4780772..df36a0b4457 100644 --- a/tests/cases/conformance/functions/functionImplementations.ts +++ b/tests/cases/conformance/functions/functionImplementations.ts @@ -69,6 +69,10 @@ var n = function () { 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; } class Derived extends Base { private q; } @@ -119,5 +123,34 @@ function f6(): number { return; } - - +class Derived2 extends Base { private r: string; } +class AnotherClass { private x } +// 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 + if (x < 0) { return x; } + return x.toString(); +} +var f8: (x: number) => any = x => { // should be (x: number) => Base + return new Base(); + return new Derived2(); +} +var f9: (x: number) => any = x => { // should be (x: number) => Base + return new Base(); + return new Derived(); + return new Derived2(); +} +var f10: (x: number) => any = x => { // should be (x: number) => Derived | Derived1 + return new Derived(); + return new Derived2(); +} +var f11: (x: number) => any = x => { // should be (x: number) => Base | AnotherClass + return new Base(); + return new AnotherClass(); +} +var f12: (x: number) => any = x => { // should be (x: number) => Base | AnotherClass + return new Base(); + return; // should be ignored + return new AnotherClass(); +} \ No newline at end of file