Flow: Wrong refinement inferred for ReactClass<>

Created on 28 Jul 2016  路  4Comments  路  Source: facebook/flow

Consider the following example:

/* @flow */

import React from 'react';

declare function componentMapper<Props1, Props2>(c: ReactClass<Props1>, f: (arg: Props2) => Props1): ReactClass<Props2>;

type FirstProps = {x: string};
type SecondProps = {x: number};

class MyComponent extends React.Component {
    props: FirstProps;
    render() {
        return <p>{this.props.x}</p>
    }
}

function fn(props: SecondProps): FirstProps {
    return { x: props.x.toString() };
};

const MyOtherComponent: ReactClass<{wrong: string[]}> = componentMapper(MyComponent, fn);

const fnComp = () => (<MyOtherComponent wronger={'string'} />);

This type compiles fine with flow 0.29, even though the type for MyOtherComponent is wrong. Flow should infer MyOtherComponent: ReactClass<SecondProps>, but it seems to infer ReactClass<any> instead, leading to subsequent unsafe uses.

bug react

Most helpful comment

@avikchaudhuri
Are there any plans to fix This functionality? We have an application that depends very much on HOC (At this point, our application is blind to the errors associated with the HOC).

I suspect that the HOC will become increasingly popular to use :
https://github.com/acdlite/recompose/blob/master/docs/API.md

All 4 comments

It seems that just using ReactClass is enough to loose type safety (maybe due to the * usage)

// @flow

import React from 'react'

type Props = { x: string };

class MyComponent extends React.Component {
  props: Props;
  render() {
    return <p>{this.props.x}</p>
  }
}

const MyComponent2: ReactClass<Props> = MyComponent;

// <MyComponent /> // <= GOOD: error property `x`. Property not found in props of React element `MyComponent`
<MyComponent2 /> // <= BAD: ok for Flow though

Yes, ReactClass is known to be buggy right now. Will fix.

@avikchaudhuri
Are there any plans to fix This functionality? We have an application that depends very much on HOC (At this point, our application is blind to the errors associated with the HOC).

I suspect that the HOC will become increasingly popular to use :
https://github.com/acdlite/recompose/blob/master/docs/API.md

As of Flow 0.53, with some minor changes, this works as expected. The following code type-checks fine:

/* @flow */

import * as React from 'react';

type FirstProps = {x: string};
type SecondProps = {x: number};

declare function componentMapper<Props1, Props2>(c: React.ComponentType<Props1>, f: (arg: Props2) => Props1): React.ComponentType<Props2>;


class MyComponent extends React.Component<FirstProps, *> {
    props: FirstProps;
    render() {
        return <p>{this.props.x}</p>
    }
}

function fn(props: SecondProps): FirstProps {
    return { x: props.x.toString() };
};

const MyOtherComponent: React.ComponentType<SecondProps> = componentMapper(MyComponent, fn);

const fnComp = () => (<MyOtherComponent x={10} />);

But passing the wrong props or types to the wrapping component gives an error.

I think this issue can be closed. (/cc @calebmer)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jamiebuilds picture jamiebuilds  路  3Comments

ctrlplusb picture ctrlplusb  路  3Comments

Beingbook picture Beingbook  路  3Comments

damncabbage picture damncabbage  路  3Comments

john-gold picture john-gold  路  3Comments