-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Closed
Labels
Design LimitationConstraints of the existing architecture prevent this from being fixedConstraints of the existing architecture prevent this from being fixed
Description
TypeScript Version: 2.4.2
Code
function mapAssign<T, K extends keyof T>(obj: T, k: K, f: (v: T[K]) => T[K]) {
obj[k] = f(obj[k]);
}
type NoChange = {
readonly value: number
}
const obj: NoChange = {value: 5};
mapAssign(obj, "value", x => x+1);Expected behavior:
Since NoChange.value is readonly, it should not be modifiable.
Actual behavior:
The code compiles and runs, modifying obj.value.
This might just be a design limitation that can't be worked around.
If a stricter check was desirable, I could imagine it being something like this:
- if
K extends keyof Tandk: Kandx: T, thenx[k] = ewould fail, butT = {readonly [k]: any}would be okay - if
K extends !readonly keyof Tandk: Kandx: Tthenx[k] = ewould succeed, butT = {readonly [k]: any}would fail
So the above program would become
function mapAssign<T, K extends !readonly keyof T>(obj: T, k: K, f: (v: T[K]) => T[K]) {
obj[k] = f(obj[k]); // okay, since K extends !readonly keyof T
}
mapAssign(obj, "value", x => x+1); // error: Const.value is readonlyAn alternative change (which I think is much less ergonomic) would be the following:
- if
K extends keyof Tandk: Kandx: Tthenx[k] = ewould succeed, butT = {readonly [k]: any}would fail - if
K extends readonly keyof Tandk: Kandx: Tthenx[k] = ewould fail butT = {readonly [k]: any}would succeed.
So the program would be
function mapAssign<T, K extends keyof T>(obj: T, k: K, f: (v: T[K]) => T[K]) {
obj[k] = f(obj[k]);
}
mapAssign(obj, "value", x => x+1); // error: Const.value is readonlyMetadata
Metadata
Assignees
Labels
Design LimitationConstraints of the existing architecture prevent this from being fixedConstraints of the existing architecture prevent this from being fixed