TypeScript incorrectly assuming the value of a property after it is set

Viewed 80

I have an object in TypeScript with a boolean property. When I set the object's value to false, TypeScript assumes it will stay false (at least until the end of the scope), even though it's able to be changed:

const object = { property: true }; // Type is { property: boolean }

object.property = false; // Type is now { property: false }

function setObjectPropertyTrue(object: { property: boolean }) {
    object.property = true;
}

setObjectPropertyTrue(object);

if (object.property == true) { // ← tsc: "This condition will always return false"
    console.log("Object property is true!");
}

Here, the TypeScript compiler thinks the if statement will never succeed because as soon as I set the object's property to false, it assumes the property's type becomes false.

Of course I can cast object.property back to boolean in the if statement to fix the error, but this seems like a bad way of doing it? Ideally TypeScript wouldn't assume an object's property couldn't change after where it sees it is set.

1 Answers

I believe there is no proper way to give TypeScript a type hint for the possible property modification in your exact implementation.

Since you said your object is a singleton, it might make more sense to have a setter function on the object itself and make the property private by using a class (playground example):

class MyObject {
    private _property: boolean = false;
 
    setObjectPropertyTrue(){
      this._property = true;
    }

    getProperty(){
      return this._property
    }

    setProperty(value: boolean){
      this._property = value;
    }
}

const myObject: MyObject = new MyObject();

// myObject._property = false; // Property '_property' is private and only accessible within class 'MyObject'

myObject.setProperty(false)

myObject.setObjectPropertyTrue()

if (myObject.getProperty() == true) { // no error
  console.log("Object property is true!");
}

Note that I am not using set and get keywords, because in this case the same error occurs as can be seen in this playground example. This behavior of TypeScript feels a bit weird to me overall. Almost like a bug or at least a lacking feature. Might be worth opening a GitHub issue for this, if you want to get to the root of this behavior.


Simple alternative for non-singleton object

If it is just a regular object and not a singleton, going for a more functional style by returning a new object might be good enough (playground example):

function setObjectPropertyTrue(p_object: typeof object) {    
    return { 
        ...p_object,
        property: true
    }
}

object = setObjectPropertyTrue(object);
Related