facebook / facebook/flow

Intersection of two Generic Types: Is it possible?

Open
#4,899 0 comments 2 reactions 0 assignees View on GitHub
question
Dominant language
Rust
Stars
22.3k
Forks
1.9k
PR merge metrics
No merged PRs in 30d

Description

Hi peeps, really appreciate the work you've put into flow! 🏅

I have tried my best to condense this problem.

# Background
I have been struggling with typing a generic HOC we use very commonly in our codebase.

```js
const adaptDataProp = dataAdapter => ComposedComponent =>
({ data, ...rest }) => ;
```

## What it does
- Apply an adapter function **only on the `data` prop**
- `data` is a prop populated with raw API data from our GraphQL server
- `adaptDataProp`accepts:
- a `dataAdapter` function which transforms `Data => AdaptedData`, e.g:
- `const dataAdapter = ({ foo }) => ({ bar: foo });`
- a React component with props, e.g.
```js
type Props = {
bar: string,
className: string
};

const View = ({ bar, className }: Props) => (

{bar}

);
```
- `adaptDataProp` should finally return:
- a React component which can be used as follows:
```js
const ViewWithData = adaptDataProp(dataAdapter)(View);
// render
;
```

# Problem/Question

1. Intersection between two generic types do not work as expected

```js
import React from 'react';
import type { ComponentType } from 'react';

function adaptDataProp(
dataAdapter: (Data) => AdaptedData
): (ComponentType => ComponentType<{ data: Data } & OtherProps>) {
return function (
ComposedComponent: ComponentType
): (ComponentType<{ data: Data } & OtherProps>) {
return function (
props: { data: Data } & OtherProps
) {
const { data, ...rest } = props;
const adaptedData = dataAdapter(data);
return ;
};
};
}

// Error
return ;
^ props of React element `ComposedComponent`. This type is incompatible with
8: ComposedComponent: ComponentType
^ some incompatible instantiation of `OtherProps`
```

## Assumption:
- Flow would be able to infer that `OtherProps` corresponds to all the props except `data` prop, i.e.
```js
{data, ...rest} = { data: Data } & OtherProps

Data -> type of data
OtherProps -> type of rest
```

[Link to Flow](https://flow.org/try/#0JYWwDg9gTgLgBAJQKYEMDG8BmUIjgcilQ3wG4AoUSWOGATzCTgG84BhXSAOyS5gBUGTAL5xsuAkXQwy5cpgCuXDMAhc4KACYowMACIoYKAAo4wAHgNGANHACC23Uk1WUALhbDbAeRgALJChTCDAAZw9mYQA+AApyODhtIwcdGECPGNcASjgAXij7RzSXQxRyLIyOcDVeASFzFKcSozgAMjhfAKCzUIL89k4avkFGc1Yk9zhXOFF2zsDgsKic5ni4IhgFKHVFZRhVdTiEhKrIUOdToZgPS55h+sbi6bn-BZ6otYq4GNvakaQxolSh5prMOq9uiFeis1gkNlsdkoVGpvrDjmAehEgUYQaUZm1wV1FqE0TDjsc0GpQvBxqVbAA6RlEan43JwDFQijkhKUrgsrSpZzTNkTR6BGITLJc7nw7ZwcyXc6aX58FiM+nMmCiZjqgVNVyiAD0UWlCWE0vN5GEcht5CAA)

# What I have attempted
- Switching the order of the intersections, e.g. `A & B` -> `B & A`
- Tried to spread `{...Other}` instead of using Intersections

I suspect it might be related to Object spread or intersection issues. However, my understanding of using generic types and how they work might be wrong. I have tried unsuccessfully to type that HOC for many weeks now.

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.