Problem with Literal Types extracted from an object using $Values<typeof OBJECT>
- Dominant language
- JavaScript
- Stars
- 797
- Forks
- 49
- PR merge metrics
- No merged PRs in 30d
Description
This is a:
- [X] Bug Report
- [ ] Feature Request
- [ ] Question
- [ ] Other
Which concerns:
- [X] 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
```
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
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!
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.