Type Assertions

`as` — "Trust Me, TypeScript"

Type Assertions

`as Type` tells TS to treat a value as a specific type. Use sparingly — assertions can hide real bugs.

3 min read Level 2/5 #typescript#assertions#as
What you'll learn
  • Use `as Type` correctly
  • Use `as const` to lock down literal types
  • Recognize the `!` non-null assertion

A type assertion tells TypeScript “I know this is type X — trust me.” TS doesn’t verify; it just changes its view of the type.

as Type

const value = JSON.parse("{}");        // any
const user = value as User;             // treated as User

The as is a type-only construct — it has zero runtime effect.

When to Use Assertions

Sparingly. Legitimate cases:

  • DOM queries that return broad types:
const input = document.getElementById("email") as HTMLInputElement;
  • After validating with your own code:
if (isValidUser(data)) {
  const user = data as User;   // ✗ usually unnecessary — predicates already narrow
}
  • Working around library types that are too broad

When NOT to Use Assertions

Don’t use as to silence errors you don’t understand. The TS error is usually trying to tell you about a real bug.

The Non-Null Assertion — !

const el = document.getElementById("nav")!;   // asserts not null

! after an expression asserts “this isn’t null or undefined”. Same caveats — convenient, but if you’re wrong, it crashes.

as const

A special assertion that locks in the literal type of an expression:

const themes = ["light", "dark"] as const;
// type: readonly ["light", "dark"]

const config = { mode: "dev" } as const;
// type: { readonly mode: "dev" }

Without as const:

const themes = ["light", "dark"];
// type: string[]

as const is great for:

  • Configuration objects with known literal values
  • Enum-like arrays / objects
  • Letting the type inference produce narrow types

Double Assertions (Avoid)

const x = "hi" as unknown as number;

TS lets you double-assert through unknown to bypass safety checks. Almost always a code smell. If you genuinely need this, your types are wrong upstream.

satisfies — A Safer Alternative

Sometimes you want to check that a value conforms to a type WITHOUT widening:

type Config = Record<string, "dev" | "prod">;

const config = {
  api: "dev",
  cdn: "prod",
} satisfies Config;

config.api;   // "dev" — narrow type preserved

satisfies lets you validate without losing inferred narrow types. Prefer it over as when you’re checking conformance.

Up Next

Discriminated unions — the single most useful pattern in TS.

Discriminated Unions →