override readonly
I have many interfaces that have readonly properties. This is because in standard usage, those properties are indeed intended to be treated as readonly. However, when setting them up I want to be able to set those properties with some sort of override command.
Right now, I either just run with an 'any' and cast it after the fact, or just disable type checking of that line altogether. Both methods come with their own disadvantages.
This has been a sticking point in my codebase for years now, and I think this is a wise addition to the language. It keeps the language succinct and means I don't have to do strange workarounds.
The following example is NOT allowed. I think having some sort of keyword like force could help here.
interface Example {
readonly a: number,
readonly b: number,
readonly someDerivativeProperty: string
}
const row: Example = await getOneRowFromDatabase();
// example row:
// { a: 3, b: 6 }
// complete the object.
// THE BELOW IS NOT ALLOWED AND THERE IS NO WAY TO OVERRIDE IT
row.someDerivativeProperty = (row.a + row.b > 9 ? 'something' : 'something else');
My suggestion meets these guidelines:
Just create a matching type that does allow mutation:
type Mutable<T> = { -readonly [P in keyof T]: T[P] }
const row: Mutable<Example> = await getOneRowFromDatabase();
row.someDerivativeProperty = (row.a + row.b > 9 ? 'something' : 'something else');
const done: Example = row;
Huh... nice.
That's some black magic though. I wonder if the TS team is happy with this being a solution
That is the intended solution, it's why the possibility to remove the readonly modifier as part of mapped types was added (same with making it non-optional, or vice-versa). And definitely to be preferred over another keyword like forced.