From b0e4ff6f210ad767067bdbc2f2f418e206bed282 Mon Sep 17 00:00:00 2001
From: Ryan Cavanaugh <RyanCavanaugh@users.noreply.github.com>
Date: Mon, 26 Aug 2024 12:30:27 -0700
Subject: [PATCH] `this` can be nullish (#59761)

---
 src/compiler/checker.ts                           |  1 +
 .../reference/predicateSemantics.errors.txt       |  6 +++++-
 tests/baselines/reference/predicateSemantics.js   | 10 +++++++++-
 .../reference/predicateSemantics.symbols          |  9 +++++++++
 .../baselines/reference/predicateSemantics.types  | 15 +++++++++++++++
 tests/cases/compiler/predicateSemantics.ts        |  5 +++++
 6 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 91346429b1774..e3350d48bdf7a 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -39725,6 +39725,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
             case SyntaxKind.NewExpression:
             case SyntaxKind.PropertyAccessExpression:
             case SyntaxKind.YieldExpression:
+            case SyntaxKind.ThisKeyword:
                 return PredicateSemantics.Sometimes;
             case SyntaxKind.BinaryExpression:
                 // List of operators that can produce null/undefined:
diff --git a/tests/baselines/reference/predicateSemantics.errors.txt b/tests/baselines/reference/predicateSemantics.errors.txt
index 883ce4570983b..14251121358c4 100644
--- a/tests/baselines/reference/predicateSemantics.errors.txt
+++ b/tests/baselines/reference/predicateSemantics.errors.txt
@@ -73,4 +73,8 @@ predicateSemantics.ts(36,8): error TS2872: This kind of expression is always tru
     
     // Should be OK
     console.log((cond || undefined) && 1 / cond);
-    
\ No newline at end of file
+    
+    function foo(this: Object | undefined) {
+        // Should be OK
+        return this ?? 0;
+    }
\ No newline at end of file
diff --git a/tests/baselines/reference/predicateSemantics.js b/tests/baselines/reference/predicateSemantics.js
index 4ed294189332c..eb0b66516b62c 100644
--- a/tests/baselines/reference/predicateSemantics.js
+++ b/tests/baselines/reference/predicateSemantics.js
@@ -40,7 +40,11 @@ while ((({}))) { }
 
 // Should be OK
 console.log((cond || undefined) && 1 / cond);
-
+
+function foo(this: Object | undefined) {
+    // Should be OK
+    return this ?? 0;
+}
 
 //// [predicateSemantics.js]
 var _a, _b, _c, _d, _e, _f;
@@ -80,3 +84,7 @@ while (({})) { }
 while ((({}))) { }
 // Should be OK
 console.log((cond || undefined) && 1 / cond);
+function foo() {
+    // Should be OK
+    return this !== null && this !== void 0 ? this : 0;
+}
diff --git a/tests/baselines/reference/predicateSemantics.symbols b/tests/baselines/reference/predicateSemantics.symbols
index 39ce291427a74..790e965f988cc 100644
--- a/tests/baselines/reference/predicateSemantics.symbols
+++ b/tests/baselines/reference/predicateSemantics.symbols
@@ -70,3 +70,12 @@ console.log((cond || undefined) && 1 / cond);
 >undefined : Symbol(undefined)
 >cond : Symbol(cond, Decl(predicateSemantics.ts, 0, 11))
 
+function foo(this: Object | undefined) {
+>foo : Symbol(foo, Decl(predicateSemantics.ts, 38, 45))
+>this : Symbol(this, Decl(predicateSemantics.ts, 40, 13))
+>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
+
+    // Should be OK
+    return this ?? 0;
+>this : Symbol(this, Decl(predicateSemantics.ts, 40, 13))
+}
diff --git a/tests/baselines/reference/predicateSemantics.types b/tests/baselines/reference/predicateSemantics.types
index b4f418ce33943..3d3eba6683e25 100644
--- a/tests/baselines/reference/predicateSemantics.types
+++ b/tests/baselines/reference/predicateSemantics.types
@@ -219,3 +219,18 @@ console.log((cond || undefined) && 1 / cond);
 >cond : any
 >     : ^^^
 
+function foo(this: Object | undefined) {
+>foo : (this: Object | undefined) => Object | 0
+>    : ^    ^^                  ^^^^^^^^^^^^^^^
+>this : Object
+>     : ^^^^^^
+
+    // Should be OK
+    return this ?? 0;
+>this ?? 0 : 0 | Object
+>          : ^^^^^^^^^^
+>this : Object
+>     : ^^^^^^
+>0 : 0
+>  : ^
+}
diff --git a/tests/cases/compiler/predicateSemantics.ts b/tests/cases/compiler/predicateSemantics.ts
index 4069c1da6eec7..d6e12b297b25b 100644
--- a/tests/cases/compiler/predicateSemantics.ts
+++ b/tests/cases/compiler/predicateSemantics.ts
@@ -37,3 +37,8 @@ while ((({}))) { }
 
 // Should be OK
 console.log((cond || undefined) && 1 / cond);
+
+function foo(this: Object | undefined) {
+    // Should be OK
+    return this ?? 0;
+}
\ No newline at end of file