The postfix ! tells the compiler "I guarantee this value is not null or undefined here" — removing null/undefined from its type without any runtime check.
ts
() {
.(name!.());
}
The postfix ! tells the compiler "I guarantee this value is not null or undefined here" — removing null/undefined from its type without any runtime check.
() {
.(name!.());
}
It's purely a compile-time assertion — like as, it does no runtime verification. If you're wrong, it crashes:
const el = document.getElementById("app")!; // assert non-null
el.innerHTML = "hi"; // 💥 runtime error if #app doesn't actually exist
// 1. You've logically guaranteed it, but the compiler can't see it
if (map.has(key)) map.get(key)!.doThing(); // has() proves get() isn't undefined
// 2. Class fields initialized outside the constructor (DI, lifecycle hooks)
class C { value!: string; } // definite assignment assertion
name?.toUpperCase(); // optional chaining — no crash, yields undefined
const x = name ?? "default"; // provide a fallback
if (name) name.toUpperCase(); // narrow with a real check
Each of these handles the missing case instead of asserting it away.
! is a sharp tool: it silences the null-safety the compiler is trying to give you.
It's occasionally justified (you have knowledge the compiler lacks), but overusing it reintroduces exactly the null-crash bugs strictNullChecks prevents.
Reach for ?., ??, or an explicit guard first; use ! only when you can truly prove non-nullness.