Postfiksowy ! mówi kompilatorowi "Gwarantuję, że ta wartość nie jest null lub undefined tutaj" — usuwając null/undefined z jej typu bez żadnej kontroli w runtime.
ts
() {
.(name!.());
}
Postfiksowy ! mówi kompilatorowi "Gwarantuję, że ta wartość nie jest null lub undefined tutaj" — usuwając null/undefined z jej typu bez żadnej kontroli w runtime.
() {
.(name!.());
}
To jest czystą asercją w compile-time — podobnie jak as, nie wykonuje weryfikacji w runtime. Jeśli się mylisz, program się wysypie:
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
Każda z nich obsługuje brakujący przypadek zamiast go asertować.
! to ostre narzędzie: wycisza null-safety, którą kompilator próbuje ci zapewnić.
Okasjonalnie jest uzasadniony (masz wiedzę, którą kompilator nie ma), ale nadużywanie go reintroducuje dokładnie te bugi z null-crash, które strictNullChecks zapobiega.
Sięgnij najpierw po ?., ?? lub jawną straż; używaj ! tylko wtedy, gdy możesz naprawdę udowodnić, że wartość nie jest null.