facebook / facebook/hermes

[flow-api-translator] Broken TypeScript when passing less-specific generics to more-specific generics

Open
#1,694 0 comments 0 reactions 1 assignee Claimed by @pieterv View on GitHub
enhancement
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.