Although not fully documented, Flow has a type called empty
that is somewhat similar to TypeScript's never
type.
In TypeScript, we can use never
to indicate a return type that will never happen, or to indicate an otherwise impossible branch of flow.
function neverReturns(): never {
while (true) {}
}
Similarly, we can use the empty
type in Flow, although it seems to behave in unexpected ways. In the below example, Flow thinks that the function will return undefined
, which is not really true.
function neverReturns(): empty { // error: Cannot expect empty as the return type of function because empty [1] is incompatible with implicitly-returned undefined.
while (true) {}
}
We can't use empty
to type impossible return types, or at least not for the example above. This will work if we throw an error in the function, though, which would indicate that the function does not return.
function neverReturns(): empty {
throw new Error()
}
Unfortunately, though, we can give the return value any type here, and Flow won't complain, which is odd:
function neverReturns(): number { // this shouldn't work, but it does
throw new Error()
}
The empty
type also seems to work somewhat like TypeScript's unknown
type, which is a type that simply asserts a particular value's type to be unknown. Note, though, that Flow has a type called mixed
that is specifically designed for this purpose, and empty
shouldn't be used here.
In the below example, we pass in two arguments to checkingUnknown
: a
, which is a number, and b
, which is of type unknown
. We also assert that checkingUnknown
will return a value that is of type unknown
.
Even though, we've cast a
as a number as it enters the function, we can create some flow control that checks if a
is a number. If it is a number, then we return b
, which we've asserted is unknown
.
If it isn't a number, we return it, and at that point, we really don't know what type a
is. Therefore, it's unknown
.
function checkingUnknown(a: number, b: unknown): unknown {
if (typeof a === 'number') return b
else return a
}
We can make this same kind of assertion in Flow with empty
:
function checkingEmpty(a: number, b: empty): empty {
if (typeof a === 'number') return b
else return a
}
But really, this is what Flow's mixed
type is for -- to assert a type to be unknown, and also not to completely opt out of type-checking (which is what any
would do).
function checkingMixed(a: number, b: mixed): mixed {
if (typeof a === 'number') return b
else return a
}