Skip to content

Commit fd1edd2

Browse files
authored
Merge pull request #16446 from Microsoft/fixNeverIntersection
Intersection with 'never' is always 'never'
2 parents a404eda + a74b790 commit fd1edd2

File tree

5 files changed

+119
-1
lines changed

5 files changed

+119
-1
lines changed

src/compiler/checker.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7168,6 +7168,7 @@ namespace ts {
71687168
containsAny?: boolean;
71697169
containsUndefined?: boolean;
71707170
containsNull?: boolean;
7171+
containsNever?: boolean;
71717172
containsNonWideningType?: boolean;
71727173
containsString?: boolean;
71737174
containsNumber?: boolean;
@@ -7369,10 +7370,13 @@ namespace ts {
73697370
else if (type.flags & TypeFlags.Any) {
73707371
typeSet.containsAny = true;
73717372
}
7373+
else if (type.flags & TypeFlags.Never) {
7374+
typeSet.containsNever = true;
7375+
}
73727376
else if (getObjectFlags(type) & ObjectFlags.Anonymous && isEmptyObjectType(type)) {
73737377
typeSet.containsEmptyObject = true;
73747378
}
7375-
else if (!(type.flags & TypeFlags.Never) && (strictNullChecks || !(type.flags & TypeFlags.Nullable)) && !contains(typeSet, type)) {
7379+
else if ((strictNullChecks || !(type.flags & TypeFlags.Nullable)) && !contains(typeSet, type)) {
73767380
if (type.flags & TypeFlags.Object) {
73777381
typeSet.containsObjectType = true;
73787382
}
@@ -7410,6 +7414,9 @@ namespace ts {
74107414
}
74117415
const typeSet = [] as TypeSet;
74127416
addTypesToIntersection(typeSet, types);
7417+
if (typeSet.containsNever) {
7418+
return neverType;
7419+
}
74137420
if (typeSet.containsAny) {
74147421
return anyType;
74157422
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//// [neverUnionIntersection.ts]
2+
type T01 = string | never;
3+
type T02 = string & never;
4+
type T03 = string | number | never;
5+
type T04 = string & number & never;
6+
type T05 = any | never;
7+
type T06 = any & never;
8+
type T07 = undefined | never;
9+
type T08 = undefined & never;
10+
type T09 = null | never;
11+
type T10 = null & never;
12+
type T11 = { a: string } | never;
13+
type T12 = { a: string } & never;
14+
15+
16+
//// [neverUnionIntersection.js]
17+
"use strict";
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
=== tests/cases/conformance/types/never/neverUnionIntersection.ts ===
2+
type T01 = string | never;
3+
>T01 : Symbol(T01, Decl(neverUnionIntersection.ts, 0, 0))
4+
5+
type T02 = string & never;
6+
>T02 : Symbol(T02, Decl(neverUnionIntersection.ts, 0, 26))
7+
8+
type T03 = string | number | never;
9+
>T03 : Symbol(T03, Decl(neverUnionIntersection.ts, 1, 26))
10+
11+
type T04 = string & number & never;
12+
>T04 : Symbol(T04, Decl(neverUnionIntersection.ts, 2, 35))
13+
14+
type T05 = any | never;
15+
>T05 : Symbol(T05, Decl(neverUnionIntersection.ts, 3, 35))
16+
17+
type T06 = any & never;
18+
>T06 : Symbol(T06, Decl(neverUnionIntersection.ts, 4, 23))
19+
20+
type T07 = undefined | never;
21+
>T07 : Symbol(T07, Decl(neverUnionIntersection.ts, 5, 23))
22+
23+
type T08 = undefined & never;
24+
>T08 : Symbol(T08, Decl(neverUnionIntersection.ts, 6, 29))
25+
26+
type T09 = null | never;
27+
>T09 : Symbol(T09, Decl(neverUnionIntersection.ts, 7, 29))
28+
29+
type T10 = null & never;
30+
>T10 : Symbol(T10, Decl(neverUnionIntersection.ts, 8, 24))
31+
32+
type T11 = { a: string } | never;
33+
>T11 : Symbol(T11, Decl(neverUnionIntersection.ts, 9, 24))
34+
>a : Symbol(a, Decl(neverUnionIntersection.ts, 10, 12))
35+
36+
type T12 = { a: string } & never;
37+
>T12 : Symbol(T12, Decl(neverUnionIntersection.ts, 10, 33))
38+
>a : Symbol(a, Decl(neverUnionIntersection.ts, 11, 12))
39+
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
=== tests/cases/conformance/types/never/neverUnionIntersection.ts ===
2+
type T01 = string | never;
3+
>T01 : string
4+
5+
type T02 = string & never;
6+
>T02 : never
7+
8+
type T03 = string | number | never;
9+
>T03 : T03
10+
11+
type T04 = string & number & never;
12+
>T04 : never
13+
14+
type T05 = any | never;
15+
>T05 : any
16+
17+
type T06 = any & never;
18+
>T06 : never
19+
20+
type T07 = undefined | never;
21+
>T07 : undefined
22+
23+
type T08 = undefined & never;
24+
>T08 : never
25+
26+
type T09 = null | never;
27+
>T09 : null
28+
>null : null
29+
30+
type T10 = null & never;
31+
>T10 : never
32+
>null : null
33+
34+
type T11 = { a: string } | never;
35+
>T11 : { a: string; }
36+
>a : string
37+
38+
type T12 = { a: string } & never;
39+
>T12 : never
40+
>a : string
41+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// @strict: true
2+
3+
type T01 = string | never;
4+
type T02 = string & never;
5+
type T03 = string | number | never;
6+
type T04 = string & number & never;
7+
type T05 = any | never;
8+
type T06 = any & never;
9+
type T07 = undefined | never;
10+
type T08 = undefined & never;
11+
type T09 = null | never;
12+
type T10 = null & never;
13+
type T11 = { a: string } | never;
14+
type T12 = { a: string } & never;

0 commit comments

Comments
 (0)