Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript readonly modifier stripped by aliasing

Tags:

typescript

So apparently typescript allows you to remove the readonly modifier from a type by a simple assignment like so:

function foo(x: { readonly value: string }) {
    x.value = "new value"; // This would fail, as it should
    bar(x); // But this is okay?
}

function bar(x: { value: string }) {
    x.value = "new value";
}

It seems to me that this would make it really easy to mutate a readonly field by accident, or am I missing something? Am I using readonly incorrectly? Is there any stricter alternative in typescript that would prohibit this kind of behavior?

EDIT: Since this is indeed how it works, here's a workaround that seems to help in my particular case, event though it's by no means a perfect solution:

type ConstAware<T> = { __writable: true } & { [P in keyof T]: T[P] };
type Const<T> = T extends ConstAware<any> ? { readonly [P in Exclude<keyof T, "__writable">]: T[P] } : never;

type Foo = ConstAware<{
    value: string;
}>;

function foo(x: Const<Foo>) {
    let y: Foo = x; // Not allowed, yay
    y.value = "new value";
}
like image 958
michalburger1 Avatar asked Feb 15 '26 00:02

michalburger1


1 Answers

This is a known issue, documented here. The gist of it is that the readonly modifier does not impact assignability. This does limit the usefulness of the readonly modifier unfortunately.

There is no known way to make this stricter, no compiler option, and no clever type trick to do this. I am pretty confident of this proclamation since there is no way to discern in the type system that readonly s present on a type (either in conditional or mapped types). Without this ability we can't really introduce an error to not allow the assignment.

Note This was written when Typescript 3.1 was the current version, future versions of Typescript (I hope) might prove me wrong.

like image 176
Titian Cernicova-Dragomir Avatar answered Feb 16 '26 19:02

Titian Cernicova-Dragomir