Reputation: 8065
In the following example (or on flow.org/try) type refinement doesn't seem to work when we check null/undefined via another variable.
type Position = {|
x: number,
y: number
|}
function anotherCondition(): bool{
return true;
}
function getIt(): ?Position{
return {x:7, y: 8}
}
function setIt(p:Position){
}
const pos = getIt();
const isOk = pos && anotherCondition();
isOk && setIt(pos)
But if we do it inline without isOk
variable, it works fine. But I have several places to check this condition and using a variable like isOk
make it less verbose. Is there any way to make it work? or am I missing something here?
Upvotes: 0
Views: 441
Reputation:
Instead of relying on refinements, which are evidently frequently invalidated, you rather should define a union type that reflects both cases:
// @flow
type Position = {|
x: number,
y: number
|} | null
function anotherCondition(): bool{
return true;
}
function getIt(): Position {
const r = Math.random();
return r <= 0.5 ? {x:7, y: 8} : null;
}
function setIt(p:Position){
if (p) {}
else {}
}
const pos = getIt();
setIt(pos);
Now, however, you have to take into account the different cases within the functions that except such a union type. This should still be more DRY.
I think you should avoid maybe types whenever possible and use the more accurate union types instead.
Upvotes: 1
Reputation: 2385
The problem is that your getIt
function returns an optional Position
, which means that flow
doesn't know if pos
has a value or not.
In your example given, getIt
should return a fixed Position
like (see flow.org/try):
function getIt(): Position {
return {
x:7,
y: 8,
}
}
Since you know 100% sure that pos
is of type Position
(because isOk
can only be true
if that's the case), you can explicitly typecast it to Position
(which is a dirty way, I know) like (see flow.org/try):
isOk && setIt(((pos: any): Position));
Upvotes: 1