Understanding 'as const' (const assertions) in TypeScript

avatar
Borislav Hadzhiev

Last updated: Feb 26, 2024
3 min

banner

# Understanding 'as const' in TypeScript

When using as const in TypeScript, we can set the properties of an object or the elements of an array to readonly, indicating to the language that the type in the expression will not be widened (e.g. from 42 to number).

index.ts
function sum(a: number, b: number) { return a + b; } // ๐Ÿ‘‡๏ธ const arr: readonly [3, 4] const arr = [3, 4] as const; console.log(sum(...arr)); // ๐Ÿ‘‰๏ธ 7
The code for this article is available on GitHub

We created a sum function that takes 2 numbers as parameters and returns the sum.

However, we have the numbers in an array, so we need a way to tell TypeScript that this array can only ever have 2 elements of type number.

This is when you would use a const assertion in TypeScript.

# Declaring a const array in TypeScript

The const assertion enables us to tell TypeScript that the array's type will not be widened, e.g. from [3, 4] to number[].

The array in the example becomes a readonly tuple, so its contents cannot be changed and we can safely unpack the two numbers in a call to the sum function.

If you try to change the contents of the array, you will get an error.

index.ts
function sum(a: number, b: number) { return a + b; } // ๐Ÿ‘‡๏ธ const arr: readonly [3, 4] const arr = [3, 4] as const; // โ›”๏ธ ERROR: Property 'push' does not exist on type 'readonly [3, 4]' arr.push(5);
The code for this article is available on GitHub

We used a const assertion, so the array is now a readonly tuple whose contents cannot be changed and attempting to do so causes an error during development.

If we try to call the sum function without using a const assertion, we would get an error.

index.ts
function sum(a: number, b: number) { return a + b; } // ๐Ÿ‘‡๏ธ const arr: readonly [3, 4] const arr = [3, 4]; // โ›”๏ธ Error: A spread argument must either have a tuple // type or be passed to a rest parameter. console.log(sum(...arr)); // ๐Ÿ‘‰๏ธ 7

TypeScript warns us that there is no way of knowing that the arr variable hasn't changed between its declaration and the time the sum() function was called.

When a const assertion is used, the array becomes a readonly tuple, so TypeScript can be sure that its contents will not change between its declaration and the function invocation.

# Declaring a const object in TypeScript

You can also use const assertions as a replacement for enums if you don't like using TypeScript's enum construct.

index.ts
// ๐Ÿ‘‡๏ธ const Pages: {readonly home: '/'; readonly about: '/about'...} export const Pages = { home: '/', about: '/about', contacts: '/contacts', } as const;
The code for this article is available on GitHub

If you try to change any of the properties of the object or add a new property, you would get an error.

index.ts
// ๐Ÿ‘‡๏ธ const Pages: {readonly home: '/'; readonly about: '/about'...} export const Pages = { home: '/', about: '/about', contacts: '/contacts', } as const; // โ›”๏ธ Error: Cannot assign to 'about', because it is // a read-only property Pages.about = 'hello'; // โ›”๏ธ Error: Property 'test' does not exist on type ... Pages.test = 'hello';

# Const assertions don't make an object or array fully immutable

It should be noted, however, that const contexts do not convert an expression to be fully immutable.

index.ts
const arr = ['/about', '/contacts']; // ๐Ÿ‘‡๏ธ const Pages: {readonly home: '/', menu: string[]} export const Pages = { home: '/', menu: arr, } as const; // โœ… Works Pages.menu.push('/test');
The code for this article is available on GitHub

The menu property references an external array, whose contents we are able to change.

If the array was defined in place on the object, we wouldn't be able to change its contents.

index.ts
// ๐Ÿ‘‡๏ธ const Pages: {readonly home: '/', readonly menu: string[]} export const Pages = { home: '/', menu: ['/about'], } as const; // โ›”๏ธ Error: Property 'push' does not exist on type // 'readonly ["/about"]' Pages.menu.push('/test');

I've also written an article on how to change a readonly property to mutable.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev