Everyday TypeScript: Readonly
Welcome to the Readonly lesson!
This lesson is shown as static text below. However, it's designed to be used interactively. Click the button below to start!
We've seen the
ReadonlyArraytype. Sometimes we want to make objects read-only too. There are a few convenient ways to do that.The first way is to make individual properties read-only by adding
readonlyto their property declarations. Any attempt to replace areadonlyproperty is a type error.>
type User = {readonly name: stringage: number};const amir: User = {name: 'Amir', age: 36};amir.name = 'Betty';amir;Result:
type error: Cannot assign to 'name' because it is a read-only property.
>
type User = {readonly name: stringage: number};const amir: User = {name: 'Amir', age: 36};amir.age += 1;amir;Result:
{name: 'Amir', age: 37}The
readonlysyntax for properties also works in interfaces and classes.>
interface User {readonly name: string}const amir: User = {name: 'Amir'};amir.name = 'Betty';amir;Result:
type error: Cannot assign to 'name' because it is a read-only property.
>
class User {readonly name: string;constructor(name: string) {this.name = name;}}const amir = new User('Amir');amir.name = 'Betty';amir;Result:
type error: Cannot assign to 'name' because it is a read-only property.
In the last example, our class's constructor assigned to the read-only
nameproperty by doingthis.name = name. This is one case where we're allowed to write to a property even when it's read-only. If the constructor couldn't write to the read-only property then there would be no way to set the property's value at all!What if we want to make the entire object type (that is, every property) read-only? For that, there's a second way: we can use
Readonly<T>, a generic utility type. It automatically adds thereadonlymodifier that we saw above to every property in the type.>
type User = Readonly<{name: stringage: number}>;const amir: User = {name: 'Amir', age: 36};amir.name = 'Betty';amir.name;Result:
type error: Cannot assign to 'name' because it is a read-only property.
Unlike arrays, we can't specify a read-only object type with
readonly User; that's a type error. We have to useReadonly<User>instead.>
type User = {name: string};const amir: readonly User = {name: 'Amir'};amir.name = 'Betty';amir.name;Result:
type error: 'readonly' type modifier is only permitted on array and tuple literal types.
There are a lot of details around read-only data in TypeScript. Our recommendation is to always start by asking "what data should never change?" Then you can work out which TypeScript features solve that problem.
For example, Execute Program loads all of its courses when the backend server first boots. Then they stay in memory forever, unchanged, until the server shuts down.
We need to make sure that our code never accidentally changes that course data, for example by calling
.sort()on an array. Based on that need, we've made all of the course data read-only usingreadonly,Readonly, andReadonlyArray. Doing this work upfront might feel tedious, but it can prevent subtle bugs that would cause severe problems.