Reputation: 2746
An example:
class MyClass {
foo: ?string;
constructor(foo) {
this.foo = foo;
}
doSomething() {
if (!this.foo) throw new Error();
console.log('hi'); // if I comment this line, I get no errors!
const myFoo: string = this.foo;
}
}
I get the following error:
12: const myFoo: string = this.foo; ^ Cannot assign
this.foo
tomyFoo
because null or undefined 1 is incompatible with string [2].
You can see it live here.
As you can see, I do make sure that this.foo
is set. However, if after the check, there is any code executed, although that code doesn't do anything, it ignores my check.
Upvotes: 0
Views: 66
Reputation: 3211
This is caused by Flow's Refinement Validations
That also provides an example workaround.
Read only variables aren't necessarily immutable. For example, delete this.foo
doesn't cause an error (which might be a bug in flow because it seems like a clear violation of the type, but is distinct from reassignment - bug report).
Upvotes: 1
Reputation: 161677
Flow does not allow this because as far as it is concerned, the console.log()
call could change the value of this.foo
, which is right. Flow could theoretically special-case console.log
since it isn't like to have side-effects, but it could be any function call there really. If you want this to work you need to grab the value first, e.g.
doSomething() {
const foo = this.foo;
if (!foo) throw new Error();
console.log('hi');
const myFoo: string = foo;
}
or
doSomething() {
if (!foo) throw new Error();
const foo = this.foo;
console.log('hi');
const myFoo: string = foo;
}
since there is no way for the type of the foo
variable to change since it isn't reassigned anywhere.
Upvotes: 1