Flow: Flow does not recognize props type when two React components are defined in same file

Created on 13 Jan 2016  路  6Comments  路  Source: facebook/flow

I have two React components in the same file. One (FooWrapper) uses the other (FooItem). FooItem has a type annotation for its props. Flow does not seem to recognize this type annotation when the two components appear in the same file. It does however work as expected when the components appear in separate files.

I've tried narrowing this down as much as I can. Here's the failing file:

/* @flow */

import React from "react";

type Foo = { bar: string };

class FooItem extends React.Component {
    props: Foo;

    render(): ReactElement {
        return (
                <span>{this.props.bar}</span>
        );
    }
}

class FooWrapper extends React.Component {
    render(): ReactElement {
        return (
            <div>
                <FooItem bar={42} />
            </div>
        );
    }
}

With Flow 0.20.1, I get the following error:

  8:     props: Foo;
                ^^^ property `bar`. Property not found in
 21:                 <FooItem bar={42} />
                     ^^^^^^^^^^^^^^^^^^^^ type parameter `Props` of React element `FooItem`

When two components live in separate files I get the expected result:

 10:                 <FooItem bar={42} />
                     ^^^^^^^^^^^^^^^^^^^^ React element `FooItem`
 10:                 <FooItem bar={42} />
                                   ^^ number. This type is incompatible with
  5: type Foo = { bar: string };
                       ^^^^^^ string. See: fooItem.js:5

I've created a gist with the failing file and the two separate files where Flow works as expected.

react

Most helpful comment

I ran into this this morning, also. @samwgoldman told me about the bug. It looks like the current workarounds are:

  • Adding parameter annotations to your class declaration:
type FooProps = {
  blah: string;
};
class Foo extends React.Component<any, FooProps, any> {
  props: FooProps;
  ...
}
  • Using require instead of import, and @rgrochowicz mentioned above.

All 6 comments

Interestingly enough, this works if React is included with a require call instead of import:

const React = require("react");

type Foo = { bar: string };

class FooItem extends React.Component {
    props: Foo;

    render(): ReactElement {
        return (
                <span>{this.props.bar}</span>
        );
    }
}

class FooWrapper extends React.Component {
    render(): ReactElement {
        return (
            <div>
                <FooItem bar={42} />
            </div>
        );
    }
}

Outputs the correct error:

test.js:20:17,36: React element `FooItem`
Error:
test.js:20:31,32: number
This type is incompatible with
test.js:4:19,24: string

Found 1 error

Also running into this issue, anyone find a solution?

I ran into this this morning, also. @samwgoldman told me about the bug. It looks like the current workarounds are:

  • Adding parameter annotations to your class declaration:
type FooProps = {
  blah: string;
};
class Foo extends React.Component<any, FooProps, any> {
  props: FooProps;
  ...
}
  • Using require instead of import, and @rgrochowicz mentioned above.

looks like this will be fixed in the next release see https://github.com/facebook/flow/commit/225f15a7ada3aa60666d20695b5945c3bacdbf36

So I suppose this one can be closed? Who should we ping for this?

This probably can be closed.
/cc @vkurchatkin

Was this page helpful?
0 / 5 - 0 ratings