It is possible to create a DeepReadonly
type like this:
type DeepReadonly = {
readonly [P in keyof T]: DeepReadonly;
};
You can have a readonly array:
interface ReadonlyArray extends Array {
readonly [n: number]: T;
}
let a = [] as ReadonlyArray;
a[0] = "moo"; // error: Index signature in type 'ReadonlyArray' only permits reading
But you can't use it with your solution:
interface A {
B: { C: number; };
D: ReadonlyArray<{ E: number; }>;
}
myDeepReadonlyObject.D[0] = { E: 3 }; // still fine
The type of D
is DeepReadonly
and it won't allow the ReadonlyArray
to kick in.
I doubt that you'll manage to make it work to objects with arrays in them, you can have either deep read only for arrays or for objects if you want a generic interface/type and not specific ones.
For example, this will work fine:
interface A {
readonly B: { readonly C: number; };
D: ReadonlyArray<{ E: number; }>;
}
const myDeepReadonlyObject = {
B: { C: 1 },
D: [{ E: 2 }],
} as A;
myDeepReadonlyObject.B = { C: 2 }; // error
myDeepReadonlyObject.B.C = 2; // error
myDeepReadonlyObject1.D[0] = { E: 3 }; // error
But it has a specific interface to it (A
) instead of a generic one DeepReadonly
.
Another option is to use Immutable.js which comes with a builtin definition file and it's pretty easy to use.