-
Notifications
You must be signed in to change notification settings - Fork 38
Description
This is a:
- Bug Report
- Feature Request
- Question
- Other
Which concerns:
- flow-runtime
- babel-plugin-flow-runtime
- flow-runtime-validators
- flow-runtime-mobx
- flow-config-parser
- The documentation website
Background
I have been using an "enum" pattern with Flow that makes it a little easier to work with types.
First, I define some constants where they have a Literal Type for a specific string. Then I use these constants to build an object with some accessor keys. Finally, I use $Values to grab the types of each value and build a string enum for the type. Here's a real example from my application:
export const FIELD_TYPE_STRING: 'string' = 'string'
export const FIELD_TYPE_NUMBER: 'number' = 'number'
export const FIELD_TYPE_BOOLEAN: 'boolean' = 'boolean'
// ...
export const FIELD_TYPES = {
STRING: FIELD_TYPE_STRING,
NUMBER: FIELD_TYPE_NUMBER,
BOOLEAN: FIELD_TYPE_BOOLEAN,
// ...
}
export type FieldType = $Values<typeof FIELD_TYPES>
Then I can write code like this:
const type: FieldType = FIELD_TYPES.STRING
I can confirm that this pattern works fine with vanilla Flow, and Flow will raise an error if I try to assign "foo" to a variable with the FieldType type.
However, it looks like flow-runtime is struggling with these literal types, and it turns everything into string | string | string | ...
I am trying to see if I can use flow-runtime to automatically extract some of these enums and use them in other parts of my application (in a different programming language.)
What is the current behaviour?
Code (for https://gajus.github.io/flow-runtime/#/try)
import t, { reify } from 'flow-runtime'
import type { Type } from 'flow-runtime'
export const THING_TYPE_ONE: 'one' = 'one'
export const THING_TYPE_TWO: 'two' = 'two'
export const THING_TYPE_THREE: 'three' = 'three'
export const THING_TYPES = {
ONE: THING_TYPE_ONE,
TWO: THING_TYPE_TWO,
THREE: THING_TYPE_THREE,
}
type ThingType = $Values<typeof THING_TYPES>
type Thing = {
id: string | number;
name: string;
thing: ThingType;
};
const widget: Thing = {
id: 123,
name: 'Widget',
thing: 'unknown'
};
console.log(widget);
console.log(ThingType.unwrap().toString())
Output:
{
id: 123,
name: "Widget",
thing: "unknown"
}
string | string | string
What is the expected behaviour?
I am expecting the widget declaration to fail with an error like this:
Thing.thing must be one of: "one" | "two" | "three"
Expected: "one" | "two" | "three"
Actual Value: "unknown"
Actual Type: string
I am also expecting ThingType.unwrap().toString() to return "one" | "two" | "three".
Workaround
In the meantime, I could change my code and manually define the string enum:
export const FIELD_TYPE_STRING: 'string' = 'string'
export const FIELD_TYPE_NUMBER: 'number' = 'number'
export const FIELD_TYPE_BOOLEAN: 'boolean' = 'boolean'
// ...
export const FIELD_TYPES = {
STRING: FIELD_TYPE_STRING,
NUMBER: FIELD_TYPE_NUMBER,
BOOLEAN: FIELD_TYPE_BOOLEAN,
// ...
}
export type FieldType = 'string' | 'number' | 'boolean' | ...
But I would love to avoid the duplication and be able to use $Values to extract these Literal Types.
Which package versions are you using?
Latest versions on https://gajus.github.io/flow-runtime/#/try
Thank you!