3

I'm trying to write a piece of code in TypeScript that boils down to this pattern:

function test(x: {theFlag: boolean} & {readonly theFlag: boolean} ){
    x.theFlag = true;
}

But I get the following error on this line x.theFlag = true;

[ts] Cannot assign to 'theFlag' because it is a constant or a read-only property.

I don't know why TypeScript is giving me an error on this. I think logically this should be allowed.

Is there a good workaround to achieve what I'm trying to do?

I'm using TypeScript version 2.7.2.

Arash
  • 203
  • 1
  • 8

1 Answers1

2

I think the compiler is playing it safe, since the property is readonly in one of the constituent types, it is readonly in the intersection.

In 2.8 you can easily create a type that removed the readonly from any property:

type Mutable<T> = { -readonly [P in keyof T]: T[P]};
function test(x: Mutable<{theFlag: boolean} & {readonly theFlag: boolean}> ){
  x.theFlag = true;
}

In 2.7 and below, I think the following definition of Mutable should do the trick, I don't use any 2.8 syntax, but I don't have an old version to test:

type MutableHelper<T, TNames extends string> = { [P in TNames]: (T & { [name: string]: never })[P]};
type Mutable<T> = MutableHelper<T, keyof T>;
Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357
  • Regarding Typescript playing it safe, here is my mental model: `{readonly theFlag: boolean}` is the set of values that have `theFlag` with a getter, and `{theFlag: boolean}` is the set of values that have `theFlag` with both a getter and a setter. Since the latter is a subset of the former, the intersection of them should be the same as `{theFlag: boolean}`. – Arash Apr 03 '18 at 20:39
  • According to basic set theory, the intersection of {getter,setter} and {getter} is {getter}. – Hisham H M Mar 25 '21 at 02:22