I'm trying to create read-only interfaces in TS, and here is an example I've tried with the readonly
modifier propagating into subtypes:
type JsonDatum =
| string
| boolean
| number
| readonly Json[]
| Object
| null
| undefined;
interface JsonInterface {
readonly [key: string]: Json;
}
type Json = JsonDatum | JsonInterface;
interface Player extends JsonInterface {
name: string;
countryCodes: number[];
elo: number;
}
const player: Player = {
name: "John Doe",
countryCodes: [1, 2, 3],
elo: 2000
}
player.name = "123" // No problem
player.countryCodes = [] // No problem
I thought that, by adding the readonly
modifier to JsonInterface
, interfaces extending it would also have its properties readonly
. But there was no problem.
In order to make it work, I had to take this very non-DRY approach and manually add readonly
s to to all of the subtype's properties:
...
interface Player extends JsonInterface {
readonly name: string;
readonly countryCodes: number[];
readonly elo: number;
}
...
player.name = "123" // Cannot assign to 'name' because it is a read-only property.(2540)
player.countryCodes = [] // Cannot assign to 'name' because it is a read-only property.(2540)
Here is the code on TypeScript's playground.
I think I'm gonna switch my approach into the Readonly<T>
generic because it seems to be the more recommended path, but even then there seem to be problems.
(The definition of Readonly<T>
seems to close to what I'm doing though: type Readonly<T> = { readonly [P in keyof T]: T[P]; }
. And I did try to adapt the above example with Readonly<T>
, but unsuccesfully.)
Is this expected behavior? Is there a workaround without Readonly<T>
?