QuestionsTypeScript

Type assertions: as, !, and why they're unsafe

Type AssertionsEasyTypeScript

Explain type assertions (`as T`), the non-null assertion (`!`), and `as unknown as T`. Why are they escape hatches rather than conversions?

What it tests

Whether you know assertions are compile-time-only claims TS trusts, not runtime checks or casts.

Approach & answer

A type assertion `value as T` tells the compiler 'trust me, this is a T' — it changes only the STATIC type and emits zero runtime code. It is not a cast: nothing is converted or validated, so a wrong assertion silently produces a value whose real shape doesn't match its type, and the bug surfaces later as an inexplicable `undefined`. TS only allows `as` between 'sufficiently overlapping' types; `as unknown as T` launders through the top type to force any conversion, which is a loud signal you're overriding the checker entirely — reserve it for genuinely justified cases (test doubles, gradual migration). The non-null assertion `x!` asserts x isn't null/undefined without a check — handy after logic the compiler can't follow, dangerous because it removes the very guard that would catch the bug (it's erased at runtime, so `x!.foo` on a null x still throws). Prefer real narrowing (`typeof`, a type guard, `if (x)`) over assertions whenever possible: narrowing PROVES the type at runtime, assertions merely assert it. Note `as const` is a different thing — a const assertion that narrows to literal, readonly types, not an override. Rule: every `as` is a small hole in type safety; each one should be defensible in review.

Use this technique when

Casting DOM query results (`as HTMLInputElement`), narrowing after runtime logic TS can't follow, test mocks (`as unknown as T`). Avoid when a type guard would prove it.

References

ts