Skip to content

Commit 3cdb808

Browse files
authored
Use NonNullable<T> in more scenarios (#49330)
* Remove getFalsyFlags and improve getNonNullableType * Apply getNonNullableType to left operand of || operator * Accept new baselines * Add tests
1 parent 75f4e95 commit 3cdb808

14 files changed

+395
-110
lines changed

src/compiler/checker.ts

Lines changed: 70 additions & 91 deletions
Large diffs are not rendered by default.

tests/baselines/reference/discriminatedUnionJsxElement.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ function Menu<MenuItemVariant extends ListItemVariant = ListItemVariant.OneLine>
1414
>data : IData<MenuItemVariant>
1515

1616
const listItemVariant = data.menuItemsVariant ?? ListItemVariant.OneLine;
17-
>listItemVariant : ListItemVariant.OneLine | NonNullable<MenuItemVariant>
18-
>data.menuItemsVariant ?? ListItemVariant.OneLine : ListItemVariant.OneLine | NonNullable<MenuItemVariant>
17+
>listItemVariant : ListItemVariant.OneLine | MenuItemVariant
18+
>data.menuItemsVariant ?? ListItemVariant.OneLine : ListItemVariant.OneLine | MenuItemVariant
1919
>data.menuItemsVariant : MenuItemVariant | undefined
2020
>data : IData<MenuItemVariant>
2121
>menuItemsVariant : MenuItemVariant | undefined

tests/baselines/reference/mappedTypes4.types

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@ function boxify<T>(obj: T): Boxified<T> {
3030
>obj : (T & null) | (T & object)
3131

3232
result[k] = { value: obj[k] };
33-
>result[k] = { value: obj[k] } : { value: NonNullable<T & object>[Extract<keyof T, string>]; }
33+
>result[k] = { value: obj[k] } : { value: (T & object)[Extract<keyof T, string>]; }
3434
>result[k] : Boxified<T>[Extract<keyof T, string>]
3535
>result : Boxified<T>
3636
>k : Extract<keyof T, string>
37-
>{ value: obj[k] } : { value: NonNullable<T & object>[Extract<keyof T, string>]; }
38-
>value : NonNullable<T & object>[Extract<keyof T, string>]
39-
>obj[k] : NonNullable<T & object>[Extract<keyof T, string>]
40-
>obj : NonNullable<T & object>
37+
>{ value: obj[k] } : { value: (T & object)[Extract<keyof T, string>]; }
38+
>value : (T & object)[Extract<keyof T, string>]
39+
>obj[k] : (T & object)[Extract<keyof T, string>]
40+
>obj : T & object
4141
>k : Extract<keyof T, string>
4242
}
4343
return result;

tests/baselines/reference/neverType.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ declare function infiniteLoop1(): void;
180180
declare function infiniteLoop2(): never;
181181
declare function move1(direction: "up" | "down"): 1 | -1;
182182
declare function move2(direction: "up" | "down"): 1 | -1;
183-
declare function check<T>(x: T | undefined): T;
183+
declare function check<T>(x: T | undefined): NonNullable<T>;
184184
declare class C {
185185
void1(): void;
186186
void2(): void;

tests/baselines/reference/neverType.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,11 @@ function move2(direction: "up" | "down") {
112112
}
113113

114114
function check<T>(x: T | undefined) {
115-
>check : <T>(x: T | undefined) => T
115+
>check : <T>(x: T | undefined) => NonNullable<T>
116116
>x : T | undefined
117117

118118
return x || error("Undefined value");
119-
>x || error("Undefined value") : T
119+
>x || error("Undefined value") : NonNullable<T>
120120
>x : T | undefined
121121
>error("Undefined value") : never
122122
>error : (message: string) => never

tests/baselines/reference/nonNullParameterExtendingStringAssignableToString.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ function fn<T extends string | undefined, U extends string>(one: T, two: U) {
2525
foo(two!);
2626
>foo(two!) : void
2727
>foo : (p: string) => void
28-
>two! : NonNullable<U>
28+
>two! : U
2929
>two : U
3030

3131
foo(three!); // this line is the important one
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
//// [nonNullableTypes1.ts]
2+
function f1<T>(x: T) {
3+
let y = x || "hello"; // NonNullable<T> | string
4+
}
5+
6+
function error(): never {
7+
throw new Error();
8+
}
9+
10+
function f2<T>(x: T) { // NonNullable<T>
11+
return x || error();
12+
}
13+
14+
function f3(x: unknown) {
15+
let y = x!; // {}
16+
}
17+
18+
function f4<T extends { x: string } | undefined>(obj: T) {
19+
if (obj?.x === "hello") {
20+
obj; // NonNullable<T>
21+
}
22+
if (obj?.x) {
23+
obj; // NonNullable<T>
24+
}
25+
if (typeof obj?.x === "string") {
26+
obj; // NonNullable<T>
27+
}
28+
}
29+
30+
class A {
31+
x = "hello";
32+
foo() {
33+
let zz = this?.x; // string
34+
}
35+
}
36+
37+
38+
//// [nonNullableTypes1.js]
39+
"use strict";
40+
function f1(x) {
41+
var y = x || "hello"; // NonNullable<T> | string
42+
}
43+
function error() {
44+
throw new Error();
45+
}
46+
function f2(x) {
47+
return x || error();
48+
}
49+
function f3(x) {
50+
var y = x; // {}
51+
}
52+
function f4(obj) {
53+
if ((obj === null || obj === void 0 ? void 0 : obj.x) === "hello") {
54+
obj; // NonNullable<T>
55+
}
56+
if (obj === null || obj === void 0 ? void 0 : obj.x) {
57+
obj; // NonNullable<T>
58+
}
59+
if (typeof (obj === null || obj === void 0 ? void 0 : obj.x) === "string") {
60+
obj; // NonNullable<T>
61+
}
62+
}
63+
var A = /** @class */ (function () {
64+
function A() {
65+
this.x = "hello";
66+
}
67+
A.prototype.foo = function () {
68+
var zz = this === null || this === void 0 ? void 0 : this.x; // string
69+
};
70+
return A;
71+
}());
72+
73+
74+
//// [nonNullableTypes1.d.ts]
75+
declare function f1<T>(x: T): void;
76+
declare function error(): never;
77+
declare function f2<T>(x: T): NonNullable<T>;
78+
declare function f3(x: unknown): void;
79+
declare function f4<T extends {
80+
x: string;
81+
} | undefined>(obj: T): void;
82+
declare class A {
83+
x: string;
84+
foo(): void;
85+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
=== tests/cases/compiler/nonNullableTypes1.ts ===
2+
function f1<T>(x: T) {
3+
>f1 : Symbol(f1, Decl(nonNullableTypes1.ts, 0, 0))
4+
>T : Symbol(T, Decl(nonNullableTypes1.ts, 0, 12))
5+
>x : Symbol(x, Decl(nonNullableTypes1.ts, 0, 15))
6+
>T : Symbol(T, Decl(nonNullableTypes1.ts, 0, 12))
7+
8+
let y = x || "hello"; // NonNullable<T> | string
9+
>y : Symbol(y, Decl(nonNullableTypes1.ts, 1, 7))
10+
>x : Symbol(x, Decl(nonNullableTypes1.ts, 0, 15))
11+
}
12+
13+
function error(): never {
14+
>error : Symbol(error, Decl(nonNullableTypes1.ts, 2, 1))
15+
16+
throw new Error();
17+
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
18+
}
19+
20+
function f2<T>(x: T) { // NonNullable<T>
21+
>f2 : Symbol(f2, Decl(nonNullableTypes1.ts, 6, 1))
22+
>T : Symbol(T, Decl(nonNullableTypes1.ts, 8, 12))
23+
>x : Symbol(x, Decl(nonNullableTypes1.ts, 8, 15))
24+
>T : Symbol(T, Decl(nonNullableTypes1.ts, 8, 12))
25+
26+
return x || error();
27+
>x : Symbol(x, Decl(nonNullableTypes1.ts, 8, 15))
28+
>error : Symbol(error, Decl(nonNullableTypes1.ts, 2, 1))
29+
}
30+
31+
function f3(x: unknown) {
32+
>f3 : Symbol(f3, Decl(nonNullableTypes1.ts, 10, 1))
33+
>x : Symbol(x, Decl(nonNullableTypes1.ts, 12, 12))
34+
35+
let y = x!; // {}
36+
>y : Symbol(y, Decl(nonNullableTypes1.ts, 13, 7))
37+
>x : Symbol(x, Decl(nonNullableTypes1.ts, 12, 12))
38+
}
39+
40+
function f4<T extends { x: string } | undefined>(obj: T) {
41+
>f4 : Symbol(f4, Decl(nonNullableTypes1.ts, 14, 1))
42+
>T : Symbol(T, Decl(nonNullableTypes1.ts, 16, 12))
43+
>x : Symbol(x, Decl(nonNullableTypes1.ts, 16, 23))
44+
>obj : Symbol(obj, Decl(nonNullableTypes1.ts, 16, 49))
45+
>T : Symbol(T, Decl(nonNullableTypes1.ts, 16, 12))
46+
47+
if (obj?.x === "hello") {
48+
>obj?.x : Symbol(x, Decl(nonNullableTypes1.ts, 16, 23))
49+
>obj : Symbol(obj, Decl(nonNullableTypes1.ts, 16, 49))
50+
>x : Symbol(x, Decl(nonNullableTypes1.ts, 16, 23))
51+
52+
obj; // NonNullable<T>
53+
>obj : Symbol(obj, Decl(nonNullableTypes1.ts, 16, 49))
54+
}
55+
if (obj?.x) {
56+
>obj?.x : Symbol(x, Decl(nonNullableTypes1.ts, 16, 23))
57+
>obj : Symbol(obj, Decl(nonNullableTypes1.ts, 16, 49))
58+
>x : Symbol(x, Decl(nonNullableTypes1.ts, 16, 23))
59+
60+
obj; // NonNullable<T>
61+
>obj : Symbol(obj, Decl(nonNullableTypes1.ts, 16, 49))
62+
}
63+
if (typeof obj?.x === "string") {
64+
>obj?.x : Symbol(x, Decl(nonNullableTypes1.ts, 16, 23))
65+
>obj : Symbol(obj, Decl(nonNullableTypes1.ts, 16, 49))
66+
>x : Symbol(x, Decl(nonNullableTypes1.ts, 16, 23))
67+
68+
obj; // NonNullable<T>
69+
>obj : Symbol(obj, Decl(nonNullableTypes1.ts, 16, 49))
70+
}
71+
}
72+
73+
class A {
74+
>A : Symbol(A, Decl(nonNullableTypes1.ts, 26, 1))
75+
76+
x = "hello";
77+
>x : Symbol(A.x, Decl(nonNullableTypes1.ts, 28, 9))
78+
79+
foo() {
80+
>foo : Symbol(A.foo, Decl(nonNullableTypes1.ts, 29, 16))
81+
82+
let zz = this?.x; // string
83+
>zz : Symbol(zz, Decl(nonNullableTypes1.ts, 31, 11))
84+
>this?.x : Symbol(A.x, Decl(nonNullableTypes1.ts, 28, 9))
85+
>this : Symbol(A, Decl(nonNullableTypes1.ts, 26, 1))
86+
>x : Symbol(A.x, Decl(nonNullableTypes1.ts, 28, 9))
87+
}
88+
}
89+
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
=== tests/cases/compiler/nonNullableTypes1.ts ===
2+
function f1<T>(x: T) {
3+
>f1 : <T>(x: T) => void
4+
>x : T
5+
6+
let y = x || "hello"; // NonNullable<T> | string
7+
>y : string | NonNullable<T>
8+
>x || "hello" : "hello" | NonNullable<T>
9+
>x : T
10+
>"hello" : "hello"
11+
}
12+
13+
function error(): never {
14+
>error : () => never
15+
16+
throw new Error();
17+
>new Error() : Error
18+
>Error : ErrorConstructor
19+
}
20+
21+
function f2<T>(x: T) { // NonNullable<T>
22+
>f2 : <T>(x: T) => NonNullable<T>
23+
>x : T
24+
25+
return x || error();
26+
>x || error() : NonNullable<T>
27+
>x : T
28+
>error() : never
29+
>error : () => never
30+
}
31+
32+
function f3(x: unknown) {
33+
>f3 : (x: unknown) => void
34+
>x : unknown
35+
36+
let y = x!; // {}
37+
>y : {}
38+
>x! : {}
39+
>x : unknown
40+
}
41+
42+
function f4<T extends { x: string } | undefined>(obj: T) {
43+
>f4 : <T extends { x: string; } | undefined>(obj: T) => void
44+
>x : string
45+
>obj : T
46+
47+
if (obj?.x === "hello") {
48+
>obj?.x === "hello" : boolean
49+
>obj?.x : string | undefined
50+
>obj : { x: string; } | undefined
51+
>x : string | undefined
52+
>"hello" : "hello"
53+
54+
obj; // NonNullable<T>
55+
>obj : NonNullable<T>
56+
}
57+
if (obj?.x) {
58+
>obj?.x : string | undefined
59+
>obj : { x: string; } | undefined
60+
>x : string | undefined
61+
62+
obj; // NonNullable<T>
63+
>obj : NonNullable<T>
64+
}
65+
if (typeof obj?.x === "string") {
66+
>typeof obj?.x === "string" : boolean
67+
>typeof obj?.x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
68+
>obj?.x : string | undefined
69+
>obj : { x: string; } | undefined
70+
>x : string | undefined
71+
>"string" : "string"
72+
73+
obj; // NonNullable<T>
74+
>obj : NonNullable<T>
75+
}
76+
}
77+
78+
class A {
79+
>A : A
80+
81+
x = "hello";
82+
>x : string
83+
>"hello" : "hello"
84+
85+
foo() {
86+
>foo : () => void
87+
88+
let zz = this?.x; // string
89+
>zz : string
90+
>this?.x : string
91+
>this : this
92+
>x : string
93+
}
94+
}
95+

tests/baselines/reference/nullishCoalescingOperator2.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ const aa6 = a6 ?? 'whatever'
7575
>'whatever' : "whatever"
7676

7777
const aa7 = a7 ?? 'whatever'
78-
>aa7 : unknown
79-
>a7 ?? 'whatever' : unknown
78+
>aa7 : {}
79+
>a7 ?? 'whatever' : {}
8080
>a7 : unknown
8181
>'whatever' : "whatever"
8282

tests/baselines/reference/nullishCoalescingOperator_es2020.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ const aa6 = a6 ?? 'whatever'
7575
>'whatever' : "whatever"
7676

7777
const aa7 = a7 ?? 'whatever'
78-
>aa7 : unknown
79-
>a7 ?? 'whatever' : unknown
78+
>aa7 : {}
79+
>a7 ?? 'whatever' : {}
8080
>a7 : unknown
8181
>'whatever' : "whatever"
8282

tests/baselines/reference/privateIdentifierChain.1.types

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ class A {
2828

2929
this?.getA().#b; // Error
3030
>this?.getA().#b : A | undefined
31-
>this?.getA() : A | undefined
32-
>this?.getA : (() => A) | undefined
31+
>this?.getA() : A
32+
>this?.getA : () => A
3333
>this : this
34-
>getA : (() => A) | undefined
34+
>getA : () => A
3535
}
3636
}
3737

tests/baselines/reference/simplifyingConditionalWithInteriorConditionalIsRelated.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ function JustConditional<T>(): ConditionalType<T> {
1515
>JustConditional : <T>() => ConditionalType<T>
1616

1717
return ConditionalOrUndefined<T>()!; // shouldn't error
18-
>ConditionalOrUndefined<T>()! : NonNullable<ConditionalType<T>>
18+
>ConditionalOrUndefined<T>()! : ConditionalType<T>
1919
>ConditionalOrUndefined<T>() : ConditionalType<T> | undefined
2020
>ConditionalOrUndefined : <T>() => ConditionalType<T> | undefined
2121
}

0 commit comments

Comments
 (0)