Rules Hub
Coding Rules Library
Rule priority, scope & exceptions
Use this to align rules with the senior-level structure (P0/P1/P2, scope, exceptions/tradeoffs).
Initialize nullable variables explicitly instead of leaving them undefined
A `let` typed as `T | null` but left unassigned is actually `undefined` at runtime; initialize it explicitly so the value matches the declared type.
Bad example
| 1 | let response: DataResponse | null; |
| 2 |
|
| 3 | if (shouldSkipFetch) { |
| 4 | // response stays uninitialized here |
| 5 | } else { |
| 6 | response = await fetchData(); |
| 7 | } |
| 8 |
|
| 9 | // response is `undefined`, not `null`, when the branch is skipped — |
| 10 | // but the type claims it can only be DataResponse | null. |
| 11 | return render(response); |
Explanation (EN)
Declaring `let response: DataResponse | null;` without an initializer leaves it `undefined` whenever a branch doesn't assign it. The type annotation says `null` is the empty case, but the real runtime value is `undefined`, so null-checks and downstream logic can misbehave. Strict tooling also flags 'Variable is used before being assigned.'
Objašnjenje (HR)
Deklaracija `let response: DataResponse | null;` bez inicijalne vrijednosti ostavlja varijablu kao `undefined` kad joj neka grana ne dodijeli vrijednost. Tip kaže da je prazno stanje `null`, ali stvarna vrijednost u izvođenju je `undefined`, pa se provjere na null i logika nizvodno mogu pogrešno ponašati. Strogi alati uz to javljaju 'Variable is used before being assigned.'
Good example
| 1 | let response: DataResponse | null = null; |
| 2 |
|
| 3 | if (shouldSkipFetch) { |
| 4 | // response is reliably null here |
| 5 | } else { |
| 6 | response = await fetchData(); |
| 7 | } |
| 8 |
|
| 9 | return render(response); |
Explanation (EN)
Initializing to `null` makes the runtime value match the declared `T | null` type in every branch, so null-checks behave as written and the 'used before being assigned' lint error disappears.
Objašnjenje (HR)
Inicijalizacija na `null` čini da stvarna vrijednost odgovara deklariranom tipu `T | null` u svakoj grani, pa se provjere na null ponašaju kako je napisano, a greška 'used before being assigned' nestaje.
Exceptions / Tradeoffs (EN)
If every code path provably assigns the variable before first use, an initializer is unnecessary — but explicit initialization is rarely wrong and is safer to default to.
Iznimke / Tradeoffi (HR)
Ako svaka putanja izvođenja dokazivo dodijeli vrijednost prije prve upotrebe, inicijalizacija nije nužna — ali eksplicitna inicijalizacija rijetko je pogrešna i sigurniji je zadani izbor.