Reputation: 28177
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?
Upvotes: 40
Views: 30637
Reputation: 1
Other option is as const
keyword.
"as const declares the content of a variable or constant as readonly and makes sure that the contents of the variable or constant are not changed" (src)
function getList() {
return [1,2,3] as const
}
const list = getList();
list[2] = 5; // error
error: Cannot assign to '2' because it is a read-only property.
result what your ide will show:
function getList(): readonly [1, 2, 3]
pro: is it clean (no need to define return type manually or create new type)
con: not explicit
Upvotes: 0
Reputation: 9
You can use Object.freeze
to return a readonly array without using any type annotations:
function getList() {
return Object.freeze([1,2,3]);
}
const list = getList();
list[2] = 5; // error
console.log(list);
Upvotes: 1
Reputation: 53352
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
overArray
when no mutation is intended, it's often been a pain given that arrays have a nicer syntax. Specifically,number[]
is a shorthand version ofArray<number>
, just asDate[]
is a shorthand forArray<Date>
.TypeScript 3.4 introduces a new syntax for
ReadonlyArray
using a newreadonly
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
Upvotes: 37
Reputation: 42390
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.
}
Upvotes: 38
Reputation: 8940
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
Upvotes: 6
Reputation: 39990
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);
}
Upvotes: 1