Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript return immutable/const/readonly Array

I want to have a function which returns an Array, but I want the returned Array to be readonly, so I should get a warning/error when I try to change its contents.

function getList(): readonly number[] {
   return [1,2,3];
}


const list = getList();
list[2] = 5; // This should result in a compile error, the returned list should never be changed

Can this be achieved in TypeScript?

like image 882
XCS Avatar asked Apr 24 '18 13:04

XCS


4 Answers

This seems to work...

function getList(): ReadonlyArray<number> {
    return [1, 2, 3];
}

const list = getList();

list[0] = 3; // Index signature in type 'ReadonlyArray<number>' only permits reading.

Try it in the Playground

ReadonlyArray<T> is implemented like this:

interface ReadonlyArray<T> {
    readonly [n: number]: T;
    // Rest of the interface removed for brevity.
}
like image 138
Matthew Layton Avatar answered Nov 17 '22 20:11

Matthew Layton


The very code from OP now works since TypeScript 3.4 introduced a new syntax for ReadonlyArray:

While it's good practice to use ReadonlyArray over Array when no mutation is intended, it's often been a pain given that arrays have a nicer syntax. Specifically, number[] is a shorthand version of Array<number>, just as Date[] is a shorthand for Array<Date>.

TypeScript 3.4 introduces a new syntax for ReadonlyArray using a new readonly modifier for array types.

This code now works as expected:

function getList(): readonly number[] {
   return [1,2,3];
}

const list = getList();
list[2] = 5; // <-- error

Playground.

like image 31
Borek Bernard Avatar answered Nov 17 '22 22:11

Borek Bernard


The following will make the list readonly but the items in it not:

function getList(): Readonly<number[]> {
   return [1,2,3];
}

let list = getList();
list = 10; // error
list[1] = 5 // that is fine

And this one will make the list and the items of it readonly:

function getList(): ReadonlyArray<number> {
   return [1,2,3];
}

let list = getList();
list = 10; // error
list[1] = 5 // error as well
like image 5
Avraam Mavridis Avatar answered Nov 17 '22 22:11

Avraam Mavridis


TypeScript has a ReadonlyArray<T> type that does this:

TypeScript comes with a ReadonlyArray type that is the same as Array with all mutating methods removed, so you can make sure you don’t change your arrays after creation

function getList(): ReadonlyArray<number> {
   return [1,2,3];
}

const list = getList();
list[2] = 5; // error

for (const n of list) {
    console.log(n);
}
like image 1
millimoose Avatar answered Nov 17 '22 22:11

millimoose