From 843aa6c1effe8365bb461a4a953d55eeb5dfa7cf Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 7 Jun 2016 07:51:34 -0700 Subject: [PATCH 1/2] Allow case comparison to undefined and null in strict null checking mode --- src/compiler/checker.ts | 2 +- ...llyTypedObjectLiteralReturnType.errors.txt | 18 ++++++++++++++++ ...ontextuallyTypedObjectLiteralReturnType.js | 21 +++++++++++++++++++ .../reference/equalityStrictNulls.errors.txt | 10 +++++++++ .../reference/equalityStrictNulls.js | 20 ++++++++++++++++++ tests/cases/compiler/inferFromConstraints.ts | 9 ++++++++ ...ontextuallyTypedObjectLiteralReturnType.ts | 9 ++++++++ .../comparable/equalityStrictNulls.ts | 10 +++++++++ 8 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/contextuallyTypedObjectLiteralReturnType.errors.txt create mode 100644 tests/baselines/reference/contextuallyTypedObjectLiteralReturnType.js create mode 100644 tests/cases/compiler/inferFromConstraints.ts create mode 100644 tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedObjectLiteralReturnType.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index be21090d780..60acefb6045 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15106,7 +15106,7 @@ namespace ts { // In a 'switch' statement, each 'case' expression must be of a type that is comparable // to or from the type of the 'switch' expression. const caseType = checkExpression(caseClause.expression); - if (!isTypeComparableTo(expressionType, caseType)) { + if (!isTypeEqualityComparableTo(expressionType, caseType)) { // expressionType is not comparable to caseType, try the reversed check and report errors if it fails checkTypeComparableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined); } diff --git a/tests/baselines/reference/contextuallyTypedObjectLiteralReturnType.errors.txt b/tests/baselines/reference/contextuallyTypedObjectLiteralReturnType.errors.txt new file mode 100644 index 00000000000..b010de0f761 --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedObjectLiteralReturnType.errors.txt @@ -0,0 +1,18 @@ +tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedObjectLiteralReturnType.ts(6,24): error TS7024: Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions. +tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedObjectLiteralReturnType.ts(7,38): error TS2339: Property 'length' does not exist on type 'number'. + + +==== tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedObjectLiteralReturnType.ts (2 errors) ==== + function id(x: T): T { return x }; + // Correct: type of fnWrapper is (y: number) => { y: number } + var fn = function(y: number) { return { y } }; + var fnWrapper = id(fn); + // Incorrect: type of inlineWrapper is (z: number) => any + var inlineWrapper = id(function(z: number) { return { z } }); + ~~~~~~~~ +!!! error TS7024: Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions. + let error1: number = fnWrapper(12).y.length; // should error + ~~~~~~ +!!! error TS2339: Property 'length' does not exist on type 'number'. + let error2: number = inlineWrapper(12).z.length; // should error + \ No newline at end of file diff --git a/tests/baselines/reference/contextuallyTypedObjectLiteralReturnType.js b/tests/baselines/reference/contextuallyTypedObjectLiteralReturnType.js new file mode 100644 index 00000000000..b687eaab5f5 --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedObjectLiteralReturnType.js @@ -0,0 +1,21 @@ +//// [contextuallyTypedObjectLiteralReturnType.ts] +function id(x: T): T { return x }; +// Correct: type of fnWrapper is (y: number) => { y: number } +var fn = function(y: number) { return { y } }; +var fnWrapper = id(fn); +// Incorrect: type of inlineWrapper is (z: number) => any +var inlineWrapper = id(function(z: number) { return { z } }); +let error1: number = fnWrapper(12).y.length; // should error +let error2: number = inlineWrapper(12).z.length; // should error + + +//// [contextuallyTypedObjectLiteralReturnType.js] +function id(x) { return x; } +; +// Correct: type of fnWrapper is (y: number) => { y: number } +var fn = function (y) { return { y: y }; }; +var fnWrapper = id(fn); +// Incorrect: type of inlineWrapper is (z: number) => any +var inlineWrapper = id(function (z) { return { z: z }; }); +var error1 = fnWrapper(12).y.length; // should error +var error2 = inlineWrapper(12).z.length; // should error diff --git a/tests/baselines/reference/equalityStrictNulls.errors.txt b/tests/baselines/reference/equalityStrictNulls.errors.txt index 54b581c87e6..e0793542b84 100644 --- a/tests/baselines/reference/equalityStrictNulls.errors.txt +++ b/tests/baselines/reference/equalityStrictNulls.errors.txt @@ -81,4 +81,14 @@ tests/cases/conformance/types/typeRelationships/comparable/equalityStrictNulls.t !!! error TS2365: Operator '<=' cannot be applied to types 'number' and 'undefined'. } } + function f5(x: string) { + switch(x) { + case null: + break; + case undefined: + break; + default: + return; + } + } \ No newline at end of file diff --git a/tests/baselines/reference/equalityStrictNulls.js b/tests/baselines/reference/equalityStrictNulls.js index 99ff801a52c..e34e9fe9989 100644 --- a/tests/baselines/reference/equalityStrictNulls.js +++ b/tests/baselines/reference/equalityStrictNulls.js @@ -67,6 +67,16 @@ function f4(x: number) { if (x <= undefined) { } } +function f5(x: string) { + switch(x) { + case null: + break; + case undefined: + break; + default: + return; + } +} //// [equalityStrictNulls.js] @@ -134,3 +144,13 @@ function f4(x) { if (x <= undefined) { } } +function f5(x) { + switch (x) { + case null: + break; + case undefined: + break; + default: + return; + } +} diff --git a/tests/cases/compiler/inferFromConstraints.ts b/tests/cases/compiler/inferFromConstraints.ts new file mode 100644 index 00000000000..d41d5ce7c46 --- /dev/null +++ b/tests/cases/compiler/inferFromConstraints.ts @@ -0,0 +1,9 @@ +interface Ctor { + new(): T; +} +// declare function create1(ctor: Ctor): T; +declare function create2>(ctor: C): T; + +class A { a: number } +// let a1 = create1(A).a; // a: A --> OK +let a2 = create2(A).a; // a: {} --> Should be A diff --git a/tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedObjectLiteralReturnType.ts b/tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedObjectLiteralReturnType.ts new file mode 100644 index 00000000000..5e4500d1cb9 --- /dev/null +++ b/tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedObjectLiteralReturnType.ts @@ -0,0 +1,9 @@ +// @noImplicitAny: true +function id(x: T): T { return x }; +// Correct: type of fnWrapper is (y: number) => { y: number } +var fn = function(y: number) { return { y } }; +var fnWrapper = id(fn); +// Incorrect: type of inlineWrapper is (z: number) => any +var inlineWrapper = id(function(z: number) { return { z } }); +let error1: number = fnWrapper(12).y.length; // should error +let error2: number = inlineWrapper(12).z.length; // should error diff --git a/tests/cases/conformance/types/typeRelationships/comparable/equalityStrictNulls.ts b/tests/cases/conformance/types/typeRelationships/comparable/equalityStrictNulls.ts index 6b2744e8849..da46ab37a2a 100644 --- a/tests/cases/conformance/types/typeRelationships/comparable/equalityStrictNulls.ts +++ b/tests/cases/conformance/types/typeRelationships/comparable/equalityStrictNulls.ts @@ -67,3 +67,13 @@ function f4(x: number) { if (x <= undefined) { } } +function f5(x: string) { + switch(x) { + case null: + break; + case undefined: + break; + default: + return; + } +} From b4f12144d2c9571aa48db44cfc3778c3e721bec9 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 7 Jun 2016 08:17:28 -0700 Subject: [PATCH 2/2] Remove incorrectly added tests --- ...llyTypedObjectLiteralReturnType.errors.txt | 18 ---------------- ...ontextuallyTypedObjectLiteralReturnType.js | 21 ------------------- tests/cases/compiler/inferFromConstraints.ts | 9 -------- ...ontextuallyTypedObjectLiteralReturnType.ts | 9 -------- 4 files changed, 57 deletions(-) delete mode 100644 tests/baselines/reference/contextuallyTypedObjectLiteralReturnType.errors.txt delete mode 100644 tests/baselines/reference/contextuallyTypedObjectLiteralReturnType.js delete mode 100644 tests/cases/compiler/inferFromConstraints.ts delete mode 100644 tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedObjectLiteralReturnType.ts diff --git a/tests/baselines/reference/contextuallyTypedObjectLiteralReturnType.errors.txt b/tests/baselines/reference/contextuallyTypedObjectLiteralReturnType.errors.txt deleted file mode 100644 index b010de0f761..00000000000 --- a/tests/baselines/reference/contextuallyTypedObjectLiteralReturnType.errors.txt +++ /dev/null @@ -1,18 +0,0 @@ -tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedObjectLiteralReturnType.ts(6,24): error TS7024: Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions. -tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedObjectLiteralReturnType.ts(7,38): error TS2339: Property 'length' does not exist on type 'number'. - - -==== tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedObjectLiteralReturnType.ts (2 errors) ==== - function id(x: T): T { return x }; - // Correct: type of fnWrapper is (y: number) => { y: number } - var fn = function(y: number) { return { y } }; - var fnWrapper = id(fn); - // Incorrect: type of inlineWrapper is (z: number) => any - var inlineWrapper = id(function(z: number) { return { z } }); - ~~~~~~~~ -!!! error TS7024: Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions. - let error1: number = fnWrapper(12).y.length; // should error - ~~~~~~ -!!! error TS2339: Property 'length' does not exist on type 'number'. - let error2: number = inlineWrapper(12).z.length; // should error - \ No newline at end of file diff --git a/tests/baselines/reference/contextuallyTypedObjectLiteralReturnType.js b/tests/baselines/reference/contextuallyTypedObjectLiteralReturnType.js deleted file mode 100644 index b687eaab5f5..00000000000 --- a/tests/baselines/reference/contextuallyTypedObjectLiteralReturnType.js +++ /dev/null @@ -1,21 +0,0 @@ -//// [contextuallyTypedObjectLiteralReturnType.ts] -function id(x: T): T { return x }; -// Correct: type of fnWrapper is (y: number) => { y: number } -var fn = function(y: number) { return { y } }; -var fnWrapper = id(fn); -// Incorrect: type of inlineWrapper is (z: number) => any -var inlineWrapper = id(function(z: number) { return { z } }); -let error1: number = fnWrapper(12).y.length; // should error -let error2: number = inlineWrapper(12).z.length; // should error - - -//// [contextuallyTypedObjectLiteralReturnType.js] -function id(x) { return x; } -; -// Correct: type of fnWrapper is (y: number) => { y: number } -var fn = function (y) { return { y: y }; }; -var fnWrapper = id(fn); -// Incorrect: type of inlineWrapper is (z: number) => any -var inlineWrapper = id(function (z) { return { z: z }; }); -var error1 = fnWrapper(12).y.length; // should error -var error2 = inlineWrapper(12).z.length; // should error diff --git a/tests/cases/compiler/inferFromConstraints.ts b/tests/cases/compiler/inferFromConstraints.ts deleted file mode 100644 index d41d5ce7c46..00000000000 --- a/tests/cases/compiler/inferFromConstraints.ts +++ /dev/null @@ -1,9 +0,0 @@ -interface Ctor { - new(): T; -} -// declare function create1(ctor: Ctor): T; -declare function create2>(ctor: C): T; - -class A { a: number } -// let a1 = create1(A).a; // a: A --> OK -let a2 = create2(A).a; // a: {} --> Should be A diff --git a/tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedObjectLiteralReturnType.ts b/tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedObjectLiteralReturnType.ts deleted file mode 100644 index 5e4500d1cb9..00000000000 --- a/tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedObjectLiteralReturnType.ts +++ /dev/null @@ -1,9 +0,0 @@ -// @noImplicitAny: true -function id(x: T): T { return x }; -// Correct: type of fnWrapper is (y: number) => { y: number } -var fn = function(y: number) { return { y } }; -var fnWrapper = id(fn); -// Incorrect: type of inlineWrapper is (z: number) => any -var inlineWrapper = id(function(z: number) { return { z } }); -let error1: number = fnWrapper(12).y.length; // should error -let error2: number = inlineWrapper(12).z.length; // should error