From 1d2c9d8e70a1883a02aa41020c23191b0ffd00a6 Mon Sep 17 00:00:00 2001
From: Sergei Zharinov <zharinov@users.noreply.github.com>
Date: Tue, 11 Jan 2022 10:36:26 +0300
Subject: [PATCH] refactor(util/lazy): Strict null check (#13455)

* refactor(util/lazy): Strict null check

* Reimplement without `never` type cast

* Revert tsconfig.json

* Fix
---
 lib/util/lazy.ts     | 44 ++++++++++++++++++++++++++++++--------------
 tsconfig.strict.json |  2 ++
 2 files changed, 32 insertions(+), 14 deletions(-)

diff --git a/lib/util/lazy.ts b/lib/util/lazy.ts
index b998e31527..079413b359 100644
--- a/lib/util/lazy.ts
+++ b/lib/util/lazy.ts
@@ -1,27 +1,43 @@
+interface ValueResult<T> {
+  type: 'success';
+  value: T;
+}
+
+interface ErrorResult {
+  type: 'error';
+  err: Error;
+}
+
 export class Lazy<T> {
-  private _didRun = false;
-  private _value?: T;
-  private _error: Error | undefined;
+  private _result?: ValueResult<T> | ErrorResult;
 
   constructor(private readonly executor: () => T) {}
 
   hasValue(): boolean {
-    return this._didRun;
+    return !!this._result;
   }
 
   getValue(): T {
-    if (!this._didRun) {
-      try {
-        this._value = this.executor();
-      } catch (err) {
-        this._error = err;
-      } finally {
-        this._didRun = true;
+    const result = this._result;
+    if (result) {
+      if (result.type === 'success') {
+        return result.value;
       }
+
+      throw result.err;
     }
-    if (this._error) {
-      throw this._error;
+
+    return this.realizeValue();
+  }
+
+  private realizeValue(): T {
+    try {
+      const value = this.executor();
+      this._result = { type: 'success', value };
+      return value;
+    } catch (err) {
+      this._result = { type: 'error', err };
+      throw err;
     }
-    return this._value;
   }
 }
diff --git a/tsconfig.strict.json b/tsconfig.strict.json
index f985628d41..76e486bf5b 100644
--- a/tsconfig.strict.json
+++ b/tsconfig.strict.json
@@ -52,6 +52,8 @@
     "lib/util/host-rules.ts",
     "lib/util/html.ts",
     "lib/util/http/**/.ts",
+    "lib/util/lazy.ts",
+    "lib/util/lazy.spec.ts",
     "lib/util/index.ts",
     "lib/util/json-writer/code-format.ts",
     "lib/util/json-writer/editor-config.ts",
-- 
GitLab