How to Use as const in TypeScript Effectively

Unlock the power of literal types and immutability in TypeScript using the as const assertion.

What is as const in TypeScript?

In TypeScript, the as const assertion is a powerful feature that tells the compiler to treat a value with the most specific and immutable type possible.

By default, TypeScript widens literal values. For example:

const role = "admin";
// role: string

But with as const:

const role = "admin" as const;
// role: "admin"

Now, role is of type "admin" instead of string, and it’s also readonly, which prevents accidental mutations.

Why Use as const?

Using as const can dramatically improve type safety, code predictability, and developer tooling (like autocomplete). It is especially useful when working with:

  • Constant values
  • Discriminated unions
  • JSON-like config objects
  • Literal arrays and tuples

Let’s dive deeper into each use case.

1- Literal Type Inference

Without as const:

const directions = ["up", "down", "left", "right"];
// directions: string[]

With as const:

const directions = ["up", "down", "left", "right"] as const;
// directions: readonly ["up", "down", "left", "right"]

Now, directions[0] is "up" instead of string, and the array is immutable (readonly).

This is especially useful when creating strict enums or options.

2. Discriminated Unions

In strongly-typed state machines or Redux reducers, discriminated unions are gold. as const makes them easy.

I wrote an article about Discriminated Unions, please check it out here.

const loginAction = {
  type: "LOGIN",
  payload: { userId: 1 },
} as const;

// loginAction.type: "LOGIN"

Then you can define:

type Action =
  | { type: "LOGIN"; payload: { userId: number } }
  | { type: "LOGOUT" };

function reducer(state: any, action: Action) {
  switch (action.type) {
    case "LOGIN":
      return { ...state, user: action.payload.userId };
    case "LOGOUT":
      return { ...state, user: null };
  }
}

Thanks to as const, TypeScript infers the type "LOGIN" automatically.

3. Constant Configuration Objects

When working with static configurations like API routes, role maps, or feature flags, as const makes the values readonly and exact:

const config = {
  baseUrl: "https://api.example.com",
  timeout: 5000,
  retry: false,
} as const;

TypeScript now infers:

{
  readonly baseUrl: "https://api.example.com";
  readonly timeout: 5000;
  readonly retry: false;
}

This prevents accidental reassignment and improves autocomplete.

4. Tuple Types and Function Overloads

If you’re using tuple types in your TypeScript utilities or writing function overloads, as const can help preserve the literal types of tuples.

function logPosition(pos: readonly [number, number]) {
  console.log(`X: ${pos[0]}, Y: ${pos[1]}`);
}

const position = [10, 20] as const; // postion: [10, 20]
logPosition(position);

Without as const, position would be typed as number[], not [10, 20].

as const vs readonly

You might wonder: what’s the difference between as const and readonly?

  • readonly applies to class properties or interface fields.
  • as const is a runtime assertion that applies literal immutability to variables or expressions.
const myArr1: readonly number[] = [1, 2, 3];
const myArr2 = [1, 2, 3] as const;

myArr1: readonly number[]

myArr2: readonly [1, 2, 3] (more specific)

Real-World Examples

In a Node.js app, you can use as const to define constants for:

  • HTTP method literals:
const METHODS = ["GET", "POST", "PUT", "DELETE"] as const;
type Method = typeof METHODS[number]; // "GET" | "POST" | "PUT" | "DELETE"
  • Role-based access control:
const ROLES = {
  admin: "ADMIN",
  user: "USER",
  guest: "GUEST",
} as const;

type Role = typeof ROLES[keyof typeof ROLES]; // "ADMIN" | "USER" | "GUEST"

This guarantees that your roles and methods are exact and immutable, reducing runtime bugs and making your app more robust.

Conclusion

The as const assertion might seem small, but it can have a big impact on the clarity, safety, and expressiveness of your TypeScript code, especially in large projects where data structures need to be stable and predictable.

Want more dev insights like this? Subscribe to get practical tips, tutorials, and tech deep dives delivered to your inbox. No spam, unsubscribe anytime.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top