diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8630974f77f26..1ac041a3653c2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15166,7 +15166,7 @@ namespace ts { return includes & TypeFlags.IncludesWildcard ? wildcardType : anyType; } if (!strictNullChecks && includes & TypeFlags.Nullable) { - return includes & TypeFlags.Undefined ? undefinedType : nullType; + return includes & TypeFlags.IncludesEmptyObject ? neverType : includes & TypeFlags.Undefined ? undefinedType : nullType; } if (includes & TypeFlags.String && includes & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) || includes & TypeFlags.Number && includes & TypeFlags.NumberLiteral || diff --git a/tests/baselines/reference/NonNullableInNonStrictMode.js b/tests/baselines/reference/NonNullableInNonStrictMode.js new file mode 100644 index 0000000000000..e5a577ed7ba88 --- /dev/null +++ b/tests/baselines/reference/NonNullableInNonStrictMode.js @@ -0,0 +1,21 @@ +//// [NonNullableInNonStrictMode.ts] +// These should all resolve to never + +type T0 = NonNullable; +type T1 = NonNullable; +type T2 = null & {}; +type T3 = undefined & {}; +type T4 = null & undefined; +type T6 = null & { a: string } & {}; + +// Repro from #50519 + +type NonNullableNew = T & {}; +type NonNullableOld = T extends null | undefined ? never : T; + +type IsNullWithoutStrictNullChecks = NonNullableNew; +type IsAlwaysNever = NonNullableOld; + + +//// [NonNullableInNonStrictMode.js] +// These should all resolve to never diff --git a/tests/baselines/reference/NonNullableInNonStrictMode.symbols b/tests/baselines/reference/NonNullableInNonStrictMode.symbols new file mode 100644 index 0000000000000..b01bdc9cfbeee --- /dev/null +++ b/tests/baselines/reference/NonNullableInNonStrictMode.symbols @@ -0,0 +1,45 @@ +=== tests/cases/compiler/NonNullableInNonStrictMode.ts === +// These should all resolve to never + +type T0 = NonNullable; +>T0 : Symbol(T0, Decl(NonNullableInNonStrictMode.ts, 0, 0)) +>NonNullable : Symbol(NonNullable, Decl(lib.es5.d.ts, --, --)) + +type T1 = NonNullable; +>T1 : Symbol(T1, Decl(NonNullableInNonStrictMode.ts, 2, 28)) +>NonNullable : Symbol(NonNullable, Decl(lib.es5.d.ts, --, --)) + +type T2 = null & {}; +>T2 : Symbol(T2, Decl(NonNullableInNonStrictMode.ts, 3, 33)) + +type T3 = undefined & {}; +>T3 : Symbol(T3, Decl(NonNullableInNonStrictMode.ts, 4, 20)) + +type T4 = null & undefined; +>T4 : Symbol(T4, Decl(NonNullableInNonStrictMode.ts, 5, 25)) + +type T6 = null & { a: string } & {}; +>T6 : Symbol(T6, Decl(NonNullableInNonStrictMode.ts, 6, 27)) +>a : Symbol(a, Decl(NonNullableInNonStrictMode.ts, 7, 18)) + +// Repro from #50519 + +type NonNullableNew = T & {}; +>NonNullableNew : Symbol(NonNullableNew, Decl(NonNullableInNonStrictMode.ts, 7, 36)) +>T : Symbol(T, Decl(NonNullableInNonStrictMode.ts, 11, 20)) +>T : Symbol(T, Decl(NonNullableInNonStrictMode.ts, 11, 20)) + +type NonNullableOld = T extends null | undefined ? never : T; +>NonNullableOld : Symbol(NonNullableOld, Decl(NonNullableInNonStrictMode.ts, 11, 32)) +>T : Symbol(T, Decl(NonNullableInNonStrictMode.ts, 12, 20)) +>T : Symbol(T, Decl(NonNullableInNonStrictMode.ts, 12, 20)) +>T : Symbol(T, Decl(NonNullableInNonStrictMode.ts, 12, 20)) + +type IsNullWithoutStrictNullChecks = NonNullableNew; +>IsNullWithoutStrictNullChecks : Symbol(IsNullWithoutStrictNullChecks, Decl(NonNullableInNonStrictMode.ts, 12, 64)) +>NonNullableNew : Symbol(NonNullableNew, Decl(NonNullableInNonStrictMode.ts, 7, 36)) + +type IsAlwaysNever = NonNullableOld; +>IsAlwaysNever : Symbol(IsAlwaysNever, Decl(NonNullableInNonStrictMode.ts, 14, 58)) +>NonNullableOld : Symbol(NonNullableOld, Decl(NonNullableInNonStrictMode.ts, 11, 32)) + diff --git a/tests/baselines/reference/NonNullableInNonStrictMode.types b/tests/baselines/reference/NonNullableInNonStrictMode.types new file mode 100644 index 0000000000000..cb2894ce0526b --- /dev/null +++ b/tests/baselines/reference/NonNullableInNonStrictMode.types @@ -0,0 +1,43 @@ +=== tests/cases/compiler/NonNullableInNonStrictMode.ts === +// These should all resolve to never + +type T0 = NonNullable; +>T0 : never +>null : null + +type T1 = NonNullable; +>T1 : never + +type T2 = null & {}; +>T2 : never +>null : null + +type T3 = undefined & {}; +>T3 : never + +type T4 = null & undefined; +>T4 : never +>null : null + +type T6 = null & { a: string } & {}; +>T6 : never +>null : null +>a : string + +// Repro from #50519 + +type NonNullableNew = T & {}; +>NonNullableNew : NonNullableNew + +type NonNullableOld = T extends null | undefined ? never : T; +>NonNullableOld : NonNullableOld +>null : null + +type IsNullWithoutStrictNullChecks = NonNullableNew; +>IsNullWithoutStrictNullChecks : never +>null : null + +type IsAlwaysNever = NonNullableOld; +>IsAlwaysNever : never +>null : null + diff --git a/tests/baselines/reference/nonNullableAndObjectIntersections(strict=false).js b/tests/baselines/reference/nonNullableAndObjectIntersections(strict=false).js new file mode 100644 index 0000000000000..1ac2c23d4a83a --- /dev/null +++ b/tests/baselines/reference/nonNullableAndObjectIntersections(strict=false).js @@ -0,0 +1,21 @@ +//// [nonNullableAndObjectIntersections.ts] +// These should all resolve to never + +type T0 = NonNullable; +type T1 = NonNullable; +type T2 = null & {}; +type T3 = undefined & {}; +type T4 = null & undefined; +type T6 = null & { a: string } & {}; + +// Repro from #50519 + +type NonNullableNew = T & {}; +type NonNullableOld = T extends null | undefined ? never : T; + +type TestNew = NonNullableNew; +type TestOld = NonNullableOld; + + +//// [nonNullableAndObjectIntersections.js] +// These should all resolve to never diff --git a/tests/baselines/reference/nonNullableAndObjectIntersections(strict=false).symbols b/tests/baselines/reference/nonNullableAndObjectIntersections(strict=false).symbols new file mode 100644 index 0000000000000..1d4558399dbbf --- /dev/null +++ b/tests/baselines/reference/nonNullableAndObjectIntersections(strict=false).symbols @@ -0,0 +1,45 @@ +=== tests/cases/compiler/nonNullableAndObjectIntersections.ts === +// These should all resolve to never + +type T0 = NonNullable; +>T0 : Symbol(T0, Decl(nonNullableAndObjectIntersections.ts, 0, 0)) +>NonNullable : Symbol(NonNullable, Decl(lib.es5.d.ts, --, --)) + +type T1 = NonNullable; +>T1 : Symbol(T1, Decl(nonNullableAndObjectIntersections.ts, 2, 28)) +>NonNullable : Symbol(NonNullable, Decl(lib.es5.d.ts, --, --)) + +type T2 = null & {}; +>T2 : Symbol(T2, Decl(nonNullableAndObjectIntersections.ts, 3, 33)) + +type T3 = undefined & {}; +>T3 : Symbol(T3, Decl(nonNullableAndObjectIntersections.ts, 4, 20)) + +type T4 = null & undefined; +>T4 : Symbol(T4, Decl(nonNullableAndObjectIntersections.ts, 5, 25)) + +type T6 = null & { a: string } & {}; +>T6 : Symbol(T6, Decl(nonNullableAndObjectIntersections.ts, 6, 27)) +>a : Symbol(a, Decl(nonNullableAndObjectIntersections.ts, 7, 18)) + +// Repro from #50519 + +type NonNullableNew = T & {}; +>NonNullableNew : Symbol(NonNullableNew, Decl(nonNullableAndObjectIntersections.ts, 7, 36)) +>T : Symbol(T, Decl(nonNullableAndObjectIntersections.ts, 11, 20)) +>T : Symbol(T, Decl(nonNullableAndObjectIntersections.ts, 11, 20)) + +type NonNullableOld = T extends null | undefined ? never : T; +>NonNullableOld : Symbol(NonNullableOld, Decl(nonNullableAndObjectIntersections.ts, 11, 32)) +>T : Symbol(T, Decl(nonNullableAndObjectIntersections.ts, 12, 20)) +>T : Symbol(T, Decl(nonNullableAndObjectIntersections.ts, 12, 20)) +>T : Symbol(T, Decl(nonNullableAndObjectIntersections.ts, 12, 20)) + +type TestNew = NonNullableNew; +>TestNew : Symbol(TestNew, Decl(nonNullableAndObjectIntersections.ts, 12, 64)) +>NonNullableNew : Symbol(NonNullableNew, Decl(nonNullableAndObjectIntersections.ts, 7, 36)) + +type TestOld = NonNullableOld; +>TestOld : Symbol(TestOld, Decl(nonNullableAndObjectIntersections.ts, 14, 36)) +>NonNullableOld : Symbol(NonNullableOld, Decl(nonNullableAndObjectIntersections.ts, 11, 32)) + diff --git a/tests/baselines/reference/nonNullableAndObjectIntersections(strict=false).types b/tests/baselines/reference/nonNullableAndObjectIntersections(strict=false).types new file mode 100644 index 0000000000000..19b4e9c5f06e7 --- /dev/null +++ b/tests/baselines/reference/nonNullableAndObjectIntersections(strict=false).types @@ -0,0 +1,43 @@ +=== tests/cases/compiler/nonNullableAndObjectIntersections.ts === +// These should all resolve to never + +type T0 = NonNullable; +>T0 : never +>null : null + +type T1 = NonNullable; +>T1 : never + +type T2 = null & {}; +>T2 : never +>null : null + +type T3 = undefined & {}; +>T3 : never + +type T4 = null & undefined; +>T4 : never +>null : null + +type T6 = null & { a: string } & {}; +>T6 : never +>null : null +>a : string + +// Repro from #50519 + +type NonNullableNew = T & {}; +>NonNullableNew : NonNullableNew + +type NonNullableOld = T extends null | undefined ? never : T; +>NonNullableOld : NonNullableOld +>null : null + +type TestNew = NonNullableNew; +>TestNew : never +>null : null + +type TestOld = NonNullableOld; +>TestOld : never +>null : null + diff --git a/tests/baselines/reference/nonNullableAndObjectIntersections(strict=true).js b/tests/baselines/reference/nonNullableAndObjectIntersections(strict=true).js new file mode 100644 index 0000000000000..51b88571c735e --- /dev/null +++ b/tests/baselines/reference/nonNullableAndObjectIntersections(strict=true).js @@ -0,0 +1,22 @@ +//// [nonNullableAndObjectIntersections.ts] +// These should all resolve to never + +type T0 = NonNullable; +type T1 = NonNullable; +type T2 = null & {}; +type T3 = undefined & {}; +type T4 = null & undefined; +type T6 = null & { a: string } & {}; + +// Repro from #50519 + +type NonNullableNew = T & {}; +type NonNullableOld = T extends null | undefined ? never : T; + +type TestNew = NonNullableNew; +type TestOld = NonNullableOld; + + +//// [nonNullableAndObjectIntersections.js] +"use strict"; +// These should all resolve to never diff --git a/tests/baselines/reference/nonNullableAndObjectIntersections(strict=true).symbols b/tests/baselines/reference/nonNullableAndObjectIntersections(strict=true).symbols new file mode 100644 index 0000000000000..1d4558399dbbf --- /dev/null +++ b/tests/baselines/reference/nonNullableAndObjectIntersections(strict=true).symbols @@ -0,0 +1,45 @@ +=== tests/cases/compiler/nonNullableAndObjectIntersections.ts === +// These should all resolve to never + +type T0 = NonNullable; +>T0 : Symbol(T0, Decl(nonNullableAndObjectIntersections.ts, 0, 0)) +>NonNullable : Symbol(NonNullable, Decl(lib.es5.d.ts, --, --)) + +type T1 = NonNullable; +>T1 : Symbol(T1, Decl(nonNullableAndObjectIntersections.ts, 2, 28)) +>NonNullable : Symbol(NonNullable, Decl(lib.es5.d.ts, --, --)) + +type T2 = null & {}; +>T2 : Symbol(T2, Decl(nonNullableAndObjectIntersections.ts, 3, 33)) + +type T3 = undefined & {}; +>T3 : Symbol(T3, Decl(nonNullableAndObjectIntersections.ts, 4, 20)) + +type T4 = null & undefined; +>T4 : Symbol(T4, Decl(nonNullableAndObjectIntersections.ts, 5, 25)) + +type T6 = null & { a: string } & {}; +>T6 : Symbol(T6, Decl(nonNullableAndObjectIntersections.ts, 6, 27)) +>a : Symbol(a, Decl(nonNullableAndObjectIntersections.ts, 7, 18)) + +// Repro from #50519 + +type NonNullableNew = T & {}; +>NonNullableNew : Symbol(NonNullableNew, Decl(nonNullableAndObjectIntersections.ts, 7, 36)) +>T : Symbol(T, Decl(nonNullableAndObjectIntersections.ts, 11, 20)) +>T : Symbol(T, Decl(nonNullableAndObjectIntersections.ts, 11, 20)) + +type NonNullableOld = T extends null | undefined ? never : T; +>NonNullableOld : Symbol(NonNullableOld, Decl(nonNullableAndObjectIntersections.ts, 11, 32)) +>T : Symbol(T, Decl(nonNullableAndObjectIntersections.ts, 12, 20)) +>T : Symbol(T, Decl(nonNullableAndObjectIntersections.ts, 12, 20)) +>T : Symbol(T, Decl(nonNullableAndObjectIntersections.ts, 12, 20)) + +type TestNew = NonNullableNew; +>TestNew : Symbol(TestNew, Decl(nonNullableAndObjectIntersections.ts, 12, 64)) +>NonNullableNew : Symbol(NonNullableNew, Decl(nonNullableAndObjectIntersections.ts, 7, 36)) + +type TestOld = NonNullableOld; +>TestOld : Symbol(TestOld, Decl(nonNullableAndObjectIntersections.ts, 14, 36)) +>NonNullableOld : Symbol(NonNullableOld, Decl(nonNullableAndObjectIntersections.ts, 11, 32)) + diff --git a/tests/baselines/reference/nonNullableAndObjectIntersections(strict=true).types b/tests/baselines/reference/nonNullableAndObjectIntersections(strict=true).types new file mode 100644 index 0000000000000..19b4e9c5f06e7 --- /dev/null +++ b/tests/baselines/reference/nonNullableAndObjectIntersections(strict=true).types @@ -0,0 +1,43 @@ +=== tests/cases/compiler/nonNullableAndObjectIntersections.ts === +// These should all resolve to never + +type T0 = NonNullable; +>T0 : never +>null : null + +type T1 = NonNullable; +>T1 : never + +type T2 = null & {}; +>T2 : never +>null : null + +type T3 = undefined & {}; +>T3 : never + +type T4 = null & undefined; +>T4 : never +>null : null + +type T6 = null & { a: string } & {}; +>T6 : never +>null : null +>a : string + +// Repro from #50519 + +type NonNullableNew = T & {}; +>NonNullableNew : NonNullableNew + +type NonNullableOld = T extends null | undefined ? never : T; +>NonNullableOld : NonNullableOld +>null : null + +type TestNew = NonNullableNew; +>TestNew : never +>null : null + +type TestOld = NonNullableOld; +>TestOld : never +>null : null + diff --git a/tests/cases/compiler/nonNullableAndObjectIntersections.ts b/tests/cases/compiler/nonNullableAndObjectIntersections.ts new file mode 100644 index 0000000000000..a9e8319aef266 --- /dev/null +++ b/tests/cases/compiler/nonNullableAndObjectIntersections.ts @@ -0,0 +1,18 @@ +// @strict: true, false + +// These should all resolve to never + +type T0 = NonNullable; +type T1 = NonNullable; +type T2 = null & {}; +type T3 = undefined & {}; +type T4 = null & undefined; +type T6 = null & { a: string } & {}; + +// Repro from #50519 + +type NonNullableNew = T & {}; +type NonNullableOld = T extends null | undefined ? never : T; + +type TestNew = NonNullableNew; +type TestOld = NonNullableOld;