ยท new features

How to use const assertions in TypeScript

TypeScript 3.4 introduced const assertions, which allow you to claim a value as immutable. This is useful when working with arrays, as it prevents new values from being added to an existing array.

TypeScript 3.4 introduced const assertions, a feature that allows you to claim a value as immutable. This feature is particularly valuable in combination with array literals, as it prevents new values from being pushed into an existing array.

Contents

const declarations

A const declaration only makes the array reference immutable.

Example

// 'const' only makes the array reference immutable
const myArray = [1, 2, 3];
// Values of the array can still be removed
myArray.pop();
// ...or pushed
myArray.push(4);
// ... but reassignments become impossible
// TS2588: Cannot assign to 'myArray' because it is a constant.
myArray = [4];

const assertions

With a const assertion you will get immutability for your array reference and array values at design-time.

Example

// A 'const assertion' protects the reference and elements of your array
const myArray = [1, 2, 3] as const;
// TS2339: Property 'pop' does not exist on type 'readonly [1, 2, 3]'.
myArray.pop();
// TS2339: Property 'push' does not exist on type 'readonly [1, 2, 3]'.
myArray.push(4);
// TS2588: Cannot assign to 'myArray' because it is a constant.
myArray = [4];

Important note

One important thing to note is that const assertions are a TypeScript feature at design-time and do not actually make values immutable at runtime. This means that you will still be able to modify values at runtime using plain JavaScript. If you want to achieve a higher level of immutability, you can make use the Object.freeze() API.

Example

const myArray = [1, 2, 3];
// The static 'freeze' method makes your array immutable at runtime
Object.freeze(myArray);
// This will happen when you try to manipulate your array in JavaScript:
// Uncaught TypeError: Cannot add property 4, object is not extensible
myArray.push(4);

Best Practice

You can combine a const assertion with Object.freeze to get type safety at design-time and runtime:

// Protection at design-time
const myArray = [1, 2, 3] as const;
// Protection at runtime
Object.freeze(myArray);

as const with objects

A const assertion can also protect an object literal by marking its properties as readonly:

// Protect your object properties from changes at design-time
const objectLiteral = {
  age: 35,
  name: 'Benny',
} as const;
 
// TS2540: Cannot assign to 'age' because it is a read-only property.
objectLiteral.age = 30;

as const with strings

You can narrow the type for a string to a specific string using as const:

// Don't use an explicit return type to make use of type inference
function getName(firstName: string, lastName: string) {
  return `${firstName} ${lastName}` as const;
}
 
let displayName = getName('Benny', 'Code');
// TS2322: Type '"..."' is not assignable to type '`${string} ${string}`'.
displayName = '...';

Alternative Options

You can use the ReadonlyArray type of TypeScript 3.4 to disallow array value modifications at design-time:

Example

const array: ReadonlyArray<number> = [1, 2, 3];
// TS2339: Property 'pop' does not exist on type 'readonly number[]'.
array.pop();

Shorthand Syntax

const array: readonly number[] = [1, 2, 3];
// TS2339: Property 'pop' does not exist on type 'readonly number[]'.
array.pop();

Video Tutorial

Back to Blog