From f81925992c09ceb6922f2c00e7effd6418981429 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 11 Jun 2017 14:54:36 -0700 Subject: [PATCH 1/2] Intersection with 'never' type always produces 'never' --- src/compiler/checker.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bbd38ddbc5ded..f5aa57777da9b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7168,6 +7168,7 @@ namespace ts { containsAny?: boolean; containsUndefined?: boolean; containsNull?: boolean; + containsNever?: boolean; containsNonWideningType?: boolean; containsString?: boolean; containsNumber?: boolean; @@ -7369,10 +7370,13 @@ namespace ts { else if (type.flags & TypeFlags.Any) { typeSet.containsAny = true; } + else if (type.flags & TypeFlags.Never) { + typeSet.containsNever = true; + } else if (getObjectFlags(type) & ObjectFlags.Anonymous && isEmptyObjectType(type)) { typeSet.containsEmptyObject = true; } - else if (!(type.flags & TypeFlags.Never) && (strictNullChecks || !(type.flags & TypeFlags.Nullable)) && !contains(typeSet, type)) { + else if ((strictNullChecks || !(type.flags & TypeFlags.Nullable)) && !contains(typeSet, type)) { if (type.flags & TypeFlags.Object) { typeSet.containsObjectType = true; } @@ -7410,6 +7414,9 @@ namespace ts { } const typeSet = [] as TypeSet; addTypesToIntersection(typeSet, types); + if (typeSet.containsNever) { + return neverType; + } if (typeSet.containsAny) { return anyType; } From a74b790ed55f7df10972f2d546d48db262dbfb4b Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 11 Jun 2017 14:54:46 -0700 Subject: [PATCH 2/2] Add tests --- .../reference/neverUnionIntersection.js | 17 ++++++++ .../reference/neverUnionIntersection.symbols | 39 ++++++++++++++++++ .../reference/neverUnionIntersection.types | 41 +++++++++++++++++++ .../types/never/neverUnionIntersection.ts | 14 +++++++ 4 files changed, 111 insertions(+) create mode 100644 tests/baselines/reference/neverUnionIntersection.js create mode 100644 tests/baselines/reference/neverUnionIntersection.symbols create mode 100644 tests/baselines/reference/neverUnionIntersection.types create mode 100644 tests/cases/conformance/types/never/neverUnionIntersection.ts diff --git a/tests/baselines/reference/neverUnionIntersection.js b/tests/baselines/reference/neverUnionIntersection.js new file mode 100644 index 0000000000000..1e84e4b003f1f --- /dev/null +++ b/tests/baselines/reference/neverUnionIntersection.js @@ -0,0 +1,17 @@ +//// [neverUnionIntersection.ts] +type T01 = string | never; +type T02 = string & never; +type T03 = string | number | never; +type T04 = string & number & never; +type T05 = any | never; +type T06 = any & never; +type T07 = undefined | never; +type T08 = undefined & never; +type T09 = null | never; +type T10 = null & never; +type T11 = { a: string } | never; +type T12 = { a: string } & never; + + +//// [neverUnionIntersection.js] +"use strict"; diff --git a/tests/baselines/reference/neverUnionIntersection.symbols b/tests/baselines/reference/neverUnionIntersection.symbols new file mode 100644 index 0000000000000..0f56c1b3157ab --- /dev/null +++ b/tests/baselines/reference/neverUnionIntersection.symbols @@ -0,0 +1,39 @@ +=== tests/cases/conformance/types/never/neverUnionIntersection.ts === +type T01 = string | never; +>T01 : Symbol(T01, Decl(neverUnionIntersection.ts, 0, 0)) + +type T02 = string & never; +>T02 : Symbol(T02, Decl(neverUnionIntersection.ts, 0, 26)) + +type T03 = string | number | never; +>T03 : Symbol(T03, Decl(neverUnionIntersection.ts, 1, 26)) + +type T04 = string & number & never; +>T04 : Symbol(T04, Decl(neverUnionIntersection.ts, 2, 35)) + +type T05 = any | never; +>T05 : Symbol(T05, Decl(neverUnionIntersection.ts, 3, 35)) + +type T06 = any & never; +>T06 : Symbol(T06, Decl(neverUnionIntersection.ts, 4, 23)) + +type T07 = undefined | never; +>T07 : Symbol(T07, Decl(neverUnionIntersection.ts, 5, 23)) + +type T08 = undefined & never; +>T08 : Symbol(T08, Decl(neverUnionIntersection.ts, 6, 29)) + +type T09 = null | never; +>T09 : Symbol(T09, Decl(neverUnionIntersection.ts, 7, 29)) + +type T10 = null & never; +>T10 : Symbol(T10, Decl(neverUnionIntersection.ts, 8, 24)) + +type T11 = { a: string } | never; +>T11 : Symbol(T11, Decl(neverUnionIntersection.ts, 9, 24)) +>a : Symbol(a, Decl(neverUnionIntersection.ts, 10, 12)) + +type T12 = { a: string } & never; +>T12 : Symbol(T12, Decl(neverUnionIntersection.ts, 10, 33)) +>a : Symbol(a, Decl(neverUnionIntersection.ts, 11, 12)) + diff --git a/tests/baselines/reference/neverUnionIntersection.types b/tests/baselines/reference/neverUnionIntersection.types new file mode 100644 index 0000000000000..4f578052e9c23 --- /dev/null +++ b/tests/baselines/reference/neverUnionIntersection.types @@ -0,0 +1,41 @@ +=== tests/cases/conformance/types/never/neverUnionIntersection.ts === +type T01 = string | never; +>T01 : string + +type T02 = string & never; +>T02 : never + +type T03 = string | number | never; +>T03 : T03 + +type T04 = string & number & never; +>T04 : never + +type T05 = any | never; +>T05 : any + +type T06 = any & never; +>T06 : never + +type T07 = undefined | never; +>T07 : undefined + +type T08 = undefined & never; +>T08 : never + +type T09 = null | never; +>T09 : null +>null : null + +type T10 = null & never; +>T10 : never +>null : null + +type T11 = { a: string } | never; +>T11 : { a: string; } +>a : string + +type T12 = { a: string } & never; +>T12 : never +>a : string + diff --git a/tests/cases/conformance/types/never/neverUnionIntersection.ts b/tests/cases/conformance/types/never/neverUnionIntersection.ts new file mode 100644 index 0000000000000..9c5a6c6a832a3 --- /dev/null +++ b/tests/cases/conformance/types/never/neverUnionIntersection.ts @@ -0,0 +1,14 @@ +// @strict: true + +type T01 = string | never; +type T02 = string & never; +type T03 = string | number | never; +type T04 = string & number & never; +type T05 = any | never; +type T06 = any & never; +type T07 = undefined | never; +type T08 = undefined & never; +type T09 = null | never; +type T10 = null & never; +type T11 = { a: string } | never; +type T12 = { a: string } & never;