[flow-api-translator] Broken TypeScript when passing less-specific generics to more-specific generics
- Dominant language
- JavaScript
- Stars
- 11.3k
- Forks
- 859
- Avg merge
- 1h 30m
- Merged PRs (30d)
- 3
Description
## Problem
The flow-api-translator produces invalid TypeScript types for generics that pass less-specific types into generics with more-specific constraints. This makes the StyleX package types invalid, see https://github.com/facebook/stylex/issues/969 and https://github.com/facebook/stylex/pull/1020.
Currently this:
```js
declare export class Angle<+T: string | 0> {}
declare export class Color<+T: string> {}
export type CSSType<+T: null | string | number> = Angle | Color;
```
Transpiles to these TypeScript types:
```ts
export declare class Angle {}
export declare class Color {}
export type CSSType = Angle | Color;
```
But the above is invalid TypeScript because you cannot pass a type which is `null | string | number` into something requiring `string | 0` or `string`.
## Solution
As I understand what Flow is doing, this would more-accurately preserve what the Flow type does.
```ts
export type CSSType =
| (T extends (any extends Angle ? R : never) ? Angle : never)
| (T extends (any extends Color ? R : never) ? Color : never)
```
It's a little verbose, but it dynamically resolves to this:
```ts
export type CSSType =
| (T extends string | 0 ? Angle : never)
| (T extends string ? Color : never)
```
And works like so:
```ts
type ColorAngleString = CSSType; // Color | Angle
type Angle0 = CSSType<0>; // Angle<0>
```
## Additional Context
I'm not sure how hard this is to implement. There could be multiple generic types to check for example, and I'm not familiar with Flow syntax to know what all cases there could be. Implementing this would solve this issue of broken types though.
Contributor guide
Assessment
This issue has not been assessed yet.