Skip to content

Commit 843aa6c

Browse files
committed
Allow case comparison to undefined and null in strict null checking mode
1 parent 53a5b42 commit 843aa6c

8 files changed

Lines changed: 98 additions & 1 deletion

File tree

src/compiler/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15106,7 +15106,7 @@ namespace ts {
1510615106
// In a 'switch' statement, each 'case' expression must be of a type that is comparable
1510715107
// to or from the type of the 'switch' expression.
1510815108
const caseType = checkExpression(caseClause.expression);
15109-
if (!isTypeComparableTo(expressionType, caseType)) {
15109+
if (!isTypeEqualityComparableTo(expressionType, caseType)) {
1511015110
// expressionType is not comparable to caseType, try the reversed check and report errors if it fails
1511115111
checkTypeComparableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined);
1511215112
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
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.
2+
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedObjectLiteralReturnType.ts(7,38): error TS2339: Property 'length' does not exist on type 'number'.
3+
4+
5+
==== tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedObjectLiteralReturnType.ts (2 errors) ====
6+
function id<T>(x: T): T { return x };
7+
// Correct: type of fnWrapper is (y: number) => { y: number }
8+
var fn = function(y: number) { return { y } };
9+
var fnWrapper = id(fn);
10+
// Incorrect: type of inlineWrapper is (z: number) => any
11+
var inlineWrapper = id(function(z: number) { return { z } });
12+
~~~~~~~~
13+
!!! 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.
14+
let error1: number = fnWrapper(12).y.length; // should error
15+
~~~~~~
16+
!!! error TS2339: Property 'length' does not exist on type 'number'.
17+
let error2: number = inlineWrapper(12).z.length; // should error
18+
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//// [contextuallyTypedObjectLiteralReturnType.ts]
2+
function id<T>(x: T): T { return x };
3+
// Correct: type of fnWrapper is (y: number) => { y: number }
4+
var fn = function(y: number) { return { y } };
5+
var fnWrapper = id(fn);
6+
// Incorrect: type of inlineWrapper is (z: number) => any
7+
var inlineWrapper = id(function(z: number) { return { z } });
8+
let error1: number = fnWrapper(12).y.length; // should error
9+
let error2: number = inlineWrapper(12).z.length; // should error
10+
11+
12+
//// [contextuallyTypedObjectLiteralReturnType.js]
13+
function id(x) { return x; }
14+
;
15+
// Correct: type of fnWrapper is (y: number) => { y: number }
16+
var fn = function (y) { return { y: y }; };
17+
var fnWrapper = id(fn);
18+
// Incorrect: type of inlineWrapper is (z: number) => any
19+
var inlineWrapper = id(function (z) { return { z: z }; });
20+
var error1 = fnWrapper(12).y.length; // should error
21+
var error2 = inlineWrapper(12).z.length; // should error

tests/baselines/reference/equalityStrictNulls.errors.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,14 @@ tests/cases/conformance/types/typeRelationships/comparable/equalityStrictNulls.t
8181
!!! error TS2365: Operator '<=' cannot be applied to types 'number' and 'undefined'.
8282
}
8383
}
84+
function f5(x: string) {
85+
switch(x) {
86+
case null:
87+
break;
88+
case undefined:
89+
break;
90+
default:
91+
return;
92+
}
93+
}
8494

tests/baselines/reference/equalityStrictNulls.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,16 @@ function f4(x: number) {
6767
if (x <= undefined) {
6868
}
6969
}
70+
function f5(x: string) {
71+
switch(x) {
72+
case null:
73+
break;
74+
case undefined:
75+
break;
76+
default:
77+
return;
78+
}
79+
}
7080

7181

7282
//// [equalityStrictNulls.js]
@@ -134,3 +144,13 @@ function f4(x) {
134144
if (x <= undefined) {
135145
}
136146
}
147+
function f5(x) {
148+
switch (x) {
149+
case null:
150+
break;
151+
case undefined:
152+
break;
153+
default:
154+
return;
155+
}
156+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
interface Ctor<T> {
2+
new(): T;
3+
}
4+
// declare function create1<T>(ctor: Ctor<T>): T;
5+
declare function create2<T, C extends Ctor<T>>(ctor: C): T;
6+
7+
class A { a: number }
8+
// let a1 = create1(A).a; // a: A --> OK
9+
let a2 = create2(A).a; // a: {} --> Should be A
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// @noImplicitAny: true
2+
function id<T>(x: T): T { return x };
3+
// Correct: type of fnWrapper is (y: number) => { y: number }
4+
var fn = function(y: number) { return { y } };
5+
var fnWrapper = id(fn);
6+
// Incorrect: type of inlineWrapper is (z: number) => any
7+
var inlineWrapper = id(function(z: number) { return { z } });
8+
let error1: number = fnWrapper(12).y.length; // should error
9+
let error2: number = inlineWrapper(12).z.length; // should error

tests/cases/conformance/types/typeRelationships/comparable/equalityStrictNulls.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,13 @@ function f4(x: number) {
6767
if (x <= undefined) {
6868
}
6969
}
70+
function f5(x: string) {
71+
switch(x) {
72+
case null:
73+
break;
74+
case undefined:
75+
break;
76+
default:
77+
return;
78+
}
79+
}

0 commit comments

Comments
 (0)