How to Use “as const” in TypeScript (const assertions)

When should we use it?

Hi, I’m Pandhu and I’m a software engineer. Welcome to my blog. Today, we will learn about const assertion.

Let’s dive into it.

const newArray = [1,2,3,4,5] as const
const newString = 'hello' as const
const newNumber = 1 as const

You may assume those variables are immutable. It means you couldn’t modify them in the next lines. Some of your thoughts are correct, but they may be incomplete. Why? Let me tell you about it.


What is “as const”?

It is called const assertion. Const assertion was released in TypeScript v3.4 and above. According to the official website,

TypeScript 3.4 introduces a new construct for literal values called _const_ assertions. Its syntax is a type assertion with const in place of the type name (e.g. 123 as const). When we construct new literal expressions with const assertions, we can signal to the language that

No literal types in that expression should be widened (e.g. no going from "hello" to string)

Object literals get readonly properties

Array literals become readonly tuples

Honestly, I was confused regarding what exactly was explained in the documentation, but I tried finding other references to understand it. And after I got many references, I tried rewriting the code according to my understanding. So this is it.

No type widening for literal types

let a = "some words";

https://www.typescriptlang.org/play?#code/DYUwLgBAhhC8EHIDOB7AtiCB3FAnAJkgkA

If you see my screenshot above, I’m getting the explanation that a is string type. What if we edit it to be const?

const a = "some words";

And what if we reassign both of them?

1. // let
let a = 'some words'
a = 'new word' // OK

2. // let with const assertions
let a = 'some words' as const
a = 'new word' // let a: "some words" - Type '"new word"' is not assignable to type '"some words"'.

3. // const (directly)
const a = 'some words'
a = 'new word' // const a: any - Cannot assign to 'a' because it is a constant.

If you see over there, when we reassign the value with let, the a will be OK. On the other hand, if we reassign with let inside const assertions, the a would not accept and get the error. Also when you reassign with const directly (not const assertions). But you need more specific explanations for cases 2 and 3.

In case 2, we got let a: “some words”. In case 3, const a: any. Why do we get a different error?

Because when we use const assertion, the value was just one input. Straight forward. For instance,

let a = "some words"; // will be have "string"

But if you use const assertions,

let a = "some words" as const // to the point, will explain that **a just value "some words"**

In the above case, a just has one value and is specific absolutely, “some words” not any. You could not reassign with another value and it is read-only.

Object literals get read-only properties

But, what if we use it for object literals? Does it work? Let’s try it.

When we use let or const in object literals, we will still be able to change the value in it. For example,

1; // With let
let data = {
  firstName: "Pandhu",
  lastName: "Wibowo",
};

data.firstName = "Wibowo";
console.log(data);

// {   "firstName": "Wibowo",   "lastName": "Wibowo" }

2; // With const
const data = {
  firstName: "Pandhu",
  lastName: "Wibowo",
};

data.firstName = "Wibowo";
console.log(data);

// {   "firstName": "Wibowo",   "lastName": "Wibowo" }

You will still be able to change it, and it works. Because it is not read-only and just informs us if the data has two properties with string type for each property.

const data: {
    firstName: string;
    lastName: string;
}

So by doing this, we can add “as const” in a similar way when we use literal types.

const data = {
  firstName: 'Pandhu',
  lastName: 'Wibowo'
} as const

data.firstName = 'Wibowo'

console.log(data) // Cannot assign to 'firstName' because it is a read-only property.

Array literals become read-only tuples

We can also use it for array literals.

const payload = {
    fullName: 'Pandhu Wibowo',
    characteristics: ["man", 25, "husband"]
}

// Description for the object
const payload: {
    fullName: string;
    characteristics: (string | number)[];
}

We want to change it to become like this:

const payload = {
    fullName: 'Pandhu Wibowo',
    characteristics: ["man", 25, "husband"]
} as const

// Description for the object
const payload: {
    readonly fullName: "Pandhu Wibowo";
    readonly characteristics: readonly ["man", 25, "husband"];
}

If we change, we will be getting an error, and the message will look like this:

const payload = {
    fullName: 'Pandhu Wibowo',
    characteristics: ["man", 25, "husband"]
} as const

payload.characteristics.push('rich')

// Property 'push' does not exist on type 'readonly ["man", 25, "husband"]'.

Enjoyed this article?

Share it with your network to help others discover it

Continue Learning

Discover more articles on similar topics