Say I have the following constant string:
export default const FOO = 'FOO'
Say I import this in a flow annotated file like so:
import FOO from '../consts/Foo'
I then have a function:
const example = (foo : string) : {| type: FOO, foo: string |} => {
return {type: FOO, foo: foo}
}
This doesn't typecheck with:
6: const example = (foo : string) : {| type: FOO, foo: string |}=> {
^^^^^^^^^^^^^^ string. Ineligible value used in/as type annotation (did you forget 'typeof'?)
6: const example = (foo : string) : {| type: FOO, foo: string |}=> {
^^^^^^^^^^^^^^ FOO
So my questions are:
1) is it possible to use constants in flow types, how can I reproduce this behaviour?
2) Is it possible to do dependent types in flow? so for example, could I encode, through types, that the string that is returned must be the same string that is passed into the example
function?
EDIT: Clarification to part 2: Is it possible to in some way indicate that the foo
parameter passed into the example
function is in fact the same string as the string at the foo
key in the return object? Or to assert that the input and output have the same length (for say a shift cipher function). Or say contain a permutation of the same characters? (for a shuffle).
https://en.wikipedia.org/wiki/Dependent_type
A String Literal, also known as a string constant or constant string, is a string of characters enclosed in double quotes, such as "To err is human - To really foul things up requires a computer." String literals are stored in C as an array of chars, terminted by a null byte.
No Apple Pencil? No problem – Flow works with any stylus or touch input.
Instead of declaring FOO
as a const
, declare it as a disjoint union with just one branch:
type FOO = "FOO"
Then your code can be updated like this:
const example = (foo : string) : {| type: FOO, foo: string |} => {
return {type: "FOO", foo: foo}
}
If you use any value besides the exact string literal "FOO"
where a FOO
is required, then it is a compile error.
If you would prefer to keep your constant, then you'll need to name the type differently, as they would collide. So you could do:
const FOO = "FOO"
type FooType = "FOO";
const example = (foo : string) : {| type: FooType, foo: string |} => {
return {type: FOO, foo: foo}
}
Unfortunately, I can't see a way to avoid duplicating the string literal, because type disjoint union definition syntax only permits literals and types, not variables even if they are constants.
Found a workaround for the issue, Instead of using flow type inference we can specify the literal type
export default const FOO:'FOO' = 'FOO'
then in the function you can use as
const example = (foo : string) : {| type: typeof FOO, foo: string |} => {
return {type: FOO, foo: foo}
}
Because when you declare the constant type is inferred to be string also I believe flow doesn't support setting type definitions from variables or constants.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With