I am working with an interface:
interface Model {
pre: Vertices,
post: Vertices,
m: Matrix,
viewport: Vector,
halfViewport: Vector,
mouse: MouseState,
selection: boolean
}
In my application, the state object is a specific instance of Model, with the selection property initialized to false. It's important to note that there is no readonly decorator present:
const state: Model = {
...
selection : false
}
Due to performance considerations, Model values are updated directly since most properties are reference types. Consequently, there are various points in the code where these properties will be modified, sometimes deep within the call stack.
Interestingly, I have observed that it is perfectly permissible to modify the Model object's selection property within a function at the top scope:
function draw(state) { state.selection = !state.selection ... }
While I do not currently make this particular call in my code base, understanding where such modifications can occur is crucial. This becomes evident further down the stack, particularly when handling events in a React component, where an attempt is made to assign a value to selection
:
function app (S: Model) : DOMElement<HTMLAttributes, Element> {
const props = {
...
onMouseDown: function (e: MouseEvent) : void {
...
S.selection = false
}
}
return React.DOM.div(props)
}
However, this assignment results in the following error message:
Uncaught TypeError: Cannot assign to read only property 'selection' of object '#<Object>'
Initially, I double-checked for the presence of a readonly
keyword in the Model
declaration, but found none. Upon inspecting the object in Chrome debugger, it appears that the object referenced by S
is actually frozen (presumably due to `tsc` invoking `Object.freeze`). This behavior seems to be linked to TypeScript's excess property checking, where interfaces instances are scrutinized when assigned to variables or parameters. Is there a way around this limitation? It does seem inconsistent that mutations can occur in one scope but not another.