Type Assertions & Non-null

A type assertion ( value as Type ) overrides the compiler's inferred type with one you supply, while the non-null assertion ( value! ) removes null and undefined — both are compile-time only and never change the value at runtime.

Learn Type Assertions & Non-null in our free TypeScript course — an interactive lesson with runnable examples, a practice exercise and a quick reference.

Part of the free TypeScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

A type assertion is like writing your own name badge at a conference. The badge says "Senior Engineer" because you typed it — the system never verified it. If it's true, great, everyone treats you correctly. If it's a lie, nothing stops you walking around with the wrong badge until something goes wrong. The as keyword is you printing the badge; the runtime is the conference that never checks it.

1. The as Assertion: Overriding the Type

Sometimes you know more than the compiler. When a value comes back as unknown from JSON.parse , or the DOM hands you a generic , you can use as to re-label it as the precise type you expect. Crucially, this is a promise to the compiler , not a conversion — the underlying value is untouched. The older angle-bracket form means exactly the same thing, but .tsx files avoid it because it clashes with JSX tags.

2. as const and the Non-null !

Two special assertions earn their own spotlight. as const tells TypeScript to infer the narrowest possible literal type and make everything deeply readonly — perfect for fixed config and tuple-of-literals menus. The non-null assertion ! strips null and undefined from a type, turning into Element . Both are type-only: if the value really is null at runtime, ! will not save you.

3. The as unknown as T Escape Hatch

TypeScript deliberately blocks a direct assertion between two types it considers unrelated, because that's usually a bug. When you genuinely need to bridge such a gap — wrapping an untyped library, say — you route through unknown : value as unknown as T . This double assertion silences the compiler entirely, which is exactly why it's a last resort : you've switched off the safety net for that value.

🎯 Your Turn

Here's a typical assertion job: a config object parsed from JSON that you read with a known shape. Fill in the two blanks marked ___ , then run it.

No blanks this time — just a brief and a starting outline. Build the lookup yourself, run it, and check your output against the example in the comments.

Practice quiz

What does a type assertion 'value as Type' do?

  • Converts the value at runtime
  • Parses strings into numbers
  • Tells the compiler to treat the value as Type; nothing changes at runtime
  • Validates the value

Answer: Tells the compiler to treat the value as Type; nothing changes at runtime. An assertion only changes what the type checker believes; the value is untouched.

What is the result of '"42" as number' followed by + 1 at runtime?

  • '421' (string concatenation, still a string)
  • 43 (a number)
  • NaN
  • a compile error

Answer: '421' (string concatenation, still a string). The value is still the string '42', so '42' + 1 is '421'. Assertions don't convert.

Why is the angle-bracket form <Type>value avoided in .tsx files?

  • It is slower
  • It only works for numbers
  • It is deprecated everywhere
  • It clashes with JSX tag syntax

Answer: It clashes with JSX tag syntax. In .tsx the parser reads <Type> as a JSX tag, so use 'value as Type' instead.

What does 'as const' do?

  • Freezes at runtime
  • Infers the narrowest literal type and makes the value deeply readonly
  • Converts to a constant function
  • Removes null

Answer: Infers the narrowest literal type and makes the value deeply readonly. as const pins literals (e.g. 'up' stays 'up') and makes everything deeply readonly in the types.

What does the non-null assertion '!' do?

  • Removes null and undefined from a value's type (type-only)
  • Throws if the value is null
  • Converts null to a default
  • Negates a boolean

Answer: Removes null and undefined from a value's type (type-only). el!.value tells TypeScript it isn't null here, but it doesn't protect you at runtime.

What happens if you use '!' on a value that really is null at runtime?

  • TypeScript blocks it
  • It returns undefined
  • It crashes - '!' is type-only and offers no runtime guarantee
  • It returns 0

Answer: It crashes - '!' is type-only and offers no runtime guarantee. The non-null assertion is a promise; if wrong, you get a runtime crash.

Why does TypeScript block 'someString as number' directly?

  • number is a reserved word
  • string and number are unrelated, so it is likely a mistake
  • as cannot target primitives
  • it never blocks this

Answer: string and number are unrelated, so it is likely a mistake. TS rejects assertions between clearly unrelated types as a probable bug.

What is the 'as unknown as T' double assertion for?

  • A safe conversion
  • Improving inference
  • Freezing a value
  • An escape hatch to force an assertion between unrelated types - a last resort

Answer: An escape hatch to force an assertion between unrelated types - a last resort. Routing through unknown silences the checker; it disables type safety for that value.

What is the safer alternative to asserting a string to a number?

  • as number
  • A real conversion like Number(str)
  • as unknown as number
  • !str

Answer: A real conversion like Number(str). Number(str) actually produces a numeric value at runtime, unlike an assertion.

Compared with an assertion, what does narrowing (e.g. if (value)) give you?

  • Nothing extra
  • Faster code only
  • Proof of the type to both the compiler AND the runtime
  • A widened type

Answer: Proof of the type to both the compiler AND the runtime. A typeof/if check protects at runtime too; 'as' only convinces the compiler.