Flow: React.ChildrenArray not working as described in docs

Created on 17 Aug 2017  路  5Comments  路  Source: facebook/flow

Taking the example given in the docs (https://flow.org/en/docs/react/types/#toc-react-childrenarray):

import * as React from 'react';
const children: React.ChildrenArray<number> = [1, 2, 3]
const array: Array<number> = React.Children.toArray(children)

results in the the following error:

3: const array: Array<number> = React.Children.toArray(children)
                                                       ^ read-only array type. This type is incompatible with
3: const array: Array<number> = React.Children.toArray(children)
                      ^ number

https://flow.org/try/#0JYWwDg9gTgLgBAKjgQwM5wEoFNkGN4BmUEIcA5FDvmQNwBQuEAdqvLgBbAA2AJpUwC5MVGADoAwp178AglCjIAngB4mAVxAAjLFAB8cALxwA2gEYANHABMlgMwBdBs1Yp5SoXIUr1WnfqPYeGKS3HxYTKIwEJ5KABQcofwAlHSpdEA

bug

Most helpful comment

Thanks for reporting this! @asolove is right. The order we have for ChildrenArray<T> is there for a reason though, I just can鈥檛 remember what that reason was at the moment 馃槪

No matter, because this is fixed in Flow v0.54 with: https://github.com/facebook/flow/commit/e4b2c0590a81bdd1a2726708c6fe3f75cd9de839

Now for ChildrenArray<A> to ChildrenArray<B> checks we don鈥檛 expand ChildrenArray instead we check A and B directly 馃槉

This change also enables phantom types which we need for typing Relay containers 馃槈

Closing otherwise I will forget when Flow 0.54 is out 馃帀

It should be out in the next week.

All 5 comments

Apart from that transition to v0.53 has been smooth so far 馃拑 馃憤 Thanks for the awesome work!

I believe this is related to a similar issue I was seeing with React.Children.map (#4625)

I think the problem arises from the type-level recursion.

Here's the relevant code from the React typings:

  declare export type ChildrenArray<T> = $ReadOnlyArray<ChildrenArray<T>> | T;
  declare export var Children: {
    // ...
    toArray<T>(children: ChildrenArray<?T>): Array<$NonMaybeType<T>>;
  };

And here's a bit of sample code that demonstrates what's happening:

import * as React from "react";

let f: (c: React.ChildrenArray<number>) => Array<number> = 
  React.Children.toArray;

Fails with:

3: let f: (c: React.ChildrenArray<number>) => Array<number> = 
              ^ read-only array type. This type is incompatible with
3: let f: (c: React.ChildrenArray<number>) => Array<number> = 
                                                    ^ number

In contrast, this version succeeds:

let f: (c: React.ChildrenArray<number>) => Array<number | React.ChildrenArray<number>> = 
  React.Children.toArray;

So I think the type for toArray currently tells the type system to peel off one level of structure, but possibly leaving others. Presumably this happens because T _could_ unify with a nested ChildrenArray type.

Thanks for reporting this! @asolove is right. The order we have for ChildrenArray<T> is there for a reason though, I just can鈥檛 remember what that reason was at the moment 馃槪

No matter, because this is fixed in Flow v0.54 with: https://github.com/facebook/flow/commit/e4b2c0590a81bdd1a2726708c6fe3f75cd9de839

Now for ChildrenArray<A> to ChildrenArray<B> checks we don鈥檛 expand ChildrenArray instead we check A and B directly 馃槉

This change also enables phantom types which we need for typing Relay containers 馃槈

Closing otherwise I will forget when Flow 0.54 is out 馃帀

It should be out in the next week.

I am experiencing this issue, 3 years later

Was this page helpful?
0 / 5 - 0 ratings