Interface with readonly property is assignable to interface with mutable property
See original GitHub issueTypeScript Version: 2.1.4
Code
interface MutableValue<T> {
value: T;
}
interface ImmutableValue<T> {
readonly value: T;
}
let i: ImmutableValue<string> = { value: "hi" };
i.value = "Excellent, I can't change it"; // compile-time error
let m: MutableValue<string> = i;
m.value = "Oh dear, I can change it";
Expected behavior:
The assignment of i
to m
would fail, to stop us accidentally allowing value
to be modified.
Actual behavior: The assignment is allowed.
The current behaviour was a deliberate choice so this is a breaking change (or strict flag) feature request rather than a bug report!
The Handbook has this snippet:
let a: number[] = [1, 2, 3, 4];
let ro: ReadonlyArray<number> = a;
ro[0] = 12; // error!
ro.push(5); // error!
ro.length = 100; // error!
a = ro; // error!
It notes that a = ro
being an error is helpful. But this happens because ReadonlyArray
has no push
method, making it incompatible with Array
.
My example above seems “morally equivalent” to modelling the input/output flow of values with separate methods:
interface MutableValue<T> {
getValue(): T;
setValue(v: T): void;
}
interface ImmutableValue<T> {
getValue(): T;
}
declare let i: ImmutableValue<string>;
i.setValue("Excellent, I can't change it"); // compile-time error
let m: MutableValue<string> = i;
m.setValue("Oh dear, I can change it");
And sure enough, this stops the assignment of i
to m
.
Would be great if mutable and readonly properties had the same relationship as if they were modelled by separate get/set methods (which of course they might actually be, via property getter/setters).
Issue Analytics
- State:
- Created 7 years ago
- Reactions:200
- Comments:27 (6 by maintainers)
Top GitHub Comments
Worth noting that Flow already handles this correctly:
I’d be in favor of an optional flag like
--strictReadonlyChecks
to opt-in to stronger type checking for those who are willing to wade through some breaking changes.I’d love to see if there’s any progress on this. I was just teaching some engineers about TypeScript today, showing different aspects of interfaces, optional and readonly properties. I went a little off my script and showed something like above…which didn’t work how I would have expected.
I’d love to see the readonly constraint respected. It’s particularly relevant for some of the work we’re doing on the vNext of Aurelia, which is all TypeScript. We also have a lot of immutable scenarios in my day job’s codebase where it would be nice to get some help from the compiler…