BeCuriouzLearn something new every day
Type Assertions & Non-null: Overriding the Compiler
💡 Type assertions (as, <T>) and the non-null ! operator only silence the compiler — they add no runtime check, so a wrong assertion becomes a runtime crash.
Sometimes you know more about a value's type than TypeScript can prove. A type assertion lets you tell the compiler "trust me, treat this as type X." The main syntax is the as keyword: const el = document.getElementById('app') as HTMLInputElement. There's an older angle-bracket form — — that does the same thing, but it clashes with JSX, so in .tsx files only as works. Prefer as everywhere for consistency.
The key danger: an assertion performs no runtime check and no conversion. It only silences the type checker. If you're wrong, the error surfaces later — getElementById returns null when the id is missing, and asserting as HTMLInputElement hides that. Reading .value then throws Cannot read properties of null at runtime, exactly the kind of bug the type system was meant to catch.
The non-null assertion operator ! is a focused cousin: it strips null and undefined from a type without touching the rest. user!.name tells the compiler "user is definitely not null here." It's shorter than as, but carries the same risk — if user really is null, you get a runtime crash. Recall the narrowing from earlier cards: an if (user) check gives you the same non-null guarantee and is verified at runtime.
Treat all three as escape hatches, not everyday tools. Reach for a real type guard or a truthiness check first; use as or ! only when you genuinely have information the compiler can't derive — and add a runtime check when the value's origin is uncertain.