Flow: Type inference with react elements is broken

Created on 30 Oct 2018  路  6Comments  路  Source: facebook/flow

I just read the article and was excited about better flow performance.
I tried the new flow and was disappointed that obvious cases are not inferred anymore.
Type inference across functions was the greatest feature in comparison to typescript. Now we don't have it.
What is the point of flow then?

https://medium.com/flow-type/asking-for-required-annotations-64d4f9c1edf8

https://flow.org/try/#0JYWwDg9gTgLgBAKjgQwM5wEoFNkGN4BmUEIcA5FDvmQNwBQduEAdqvACLIzLbMAmWSlDgBeOAAoA3nFwALYABs+lZnAC+ASlEA+CXTgz5SlVP0G4fLsgBccaTbgBGdQBozBrHwDmWVLYDaALpuBpp0GvR0WAAekLAyLGxw7FgAbgAyOHzoYuJaIrriZgA8nNy8AkLa7nZSFlYucJ4+6Jo6eubmxXzAqXAA9NWdGmol-WU8WPyCgtURdEA

Most helpful comment

Nothing is broken, but the inferred type reaches exports in an input position in a way you might not expect -- through the inferred element type.

An element is an object with the following type:

declare type React$Element<+ElementType: React$ElementType> = {|
  +type: ElementType,
  +props: React$ElementProps<ElementType>,
  +key: React$Key | null,
  +ref: any,
|};

So in the example here:

import * as React from 'react';
const Component = ({ value }) => value;
export default <Component value={1} />

the returned value's type property is the Component function itself. This is how the unannotated props are reaching exports. For example, I could consume this module like so:

import elem from "./foo";
elem.type({ value: "something unexpected" });

All 6 comments

/cc @samwgoldman

Oh, god. It's broken even for such simple case. This is worst release ever.
https://flow.org/try/#0JYWwDg9gTgLgBAKjgQwM5wEoFNkGN4BmUEIcA5FDvmQNwBQduEAdqvAMImTNbPwC8cABQBvOADdkAGwCuWOAF8AlHH4A+CdLn06WAB6RYcJq3gAFZJT6rhK9cLpw4AHk7gWveJNlZ+IgIwKcAD0anRK9EA

Nothing is broken, but the inferred type reaches exports in an input position in a way you might not expect -- through the inferred element type.

An element is an object with the following type:

declare type React$Element<+ElementType: React$ElementType> = {|
  +type: ElementType,
  +props: React$ElementProps<ElementType>,
  +key: React$Key | null,
  +ref: any,
|};

So in the example here:

import * as React from 'react';
const Component = ({ value }) => value;
export default <Component value={1} />

the returned value's type property is the Component function itself. This is how the unannotated props are reaching exports. For example, I could consume this module like so:

import elem from "./foo";
elem.type({ value: "something unexpected" });

Thank you for explanation and really
this

import * as React from 'react';

const Component = ({ value }) => value;

export const Parent = () => (
  <div>
     <Component value={1} />
  </div>    
);

works. (as now nothing exposed to export)

This too

import * as React from 'react';

const Component = ({ value }) => value;

export const Parent = (): React.Node => (
  <Component value={1} />
);
Was this page helpful?
0 / 5 - 0 ratings