0

I have a component that I restricted to have certain types of children using flow types. However, now I have several situations where it is convenient to wrap those components in other component that just returns one of the valid components but with some defaults attached. Even grouping some of those valid components using react fragments gives me weird errors that I am unable to debug.

Here is a piece of sample code (that you can run on flow playground):

//@flow
import React from 'react'
import type { Node, Element, ChildrenArray } from 'react'

type ItemType = Element<typeof ListItem | typeof ListHeader>

type Props = {
  children: ChildrenArray<ItemType>,
}

function List({ children }: Props) {
  return <div>{children}</div>
}

type ItemProps = {
  children: Node,
  onClick?: () => void,
}

function ListItem({ children, onClick }: ItemProps) {
  return <div onClick={onClick}>{children}</div>
}

type HeaderProps = {
  children: Node,
}

function ListHeader({ children }: HeaderProps) {
  return <div>{children}</div>
}

const Row = ({ left, right }: { left: string, right: Node }): Node => {
  return (
    <ListItem>
      {left}
      <span>{right}</span>
    </ListItem>
  )
}

const x = () => (
  <List>
    <Row left="gender" right="${gender}" />
    <Row left="birthDate" right="xxx" />
    <Row left="Number" right="xxx" />
    <Row left="sendEnrollmentLetter" right="stuff" />
  </List>
)

What is the correct way of following such pattern?

On flow playground you will not see errors because, if you open the console you will see that it just blows up.

This is the concrete error I'm getting on my project:

Cannot create `List` element because in array element of property `children`: 
Either property `children` is missing in  object type [1] but exists in  `HeaderProps` [2] in property `props`. 
Or property `children` is missing in  object type [1] but exists in  `ItemProps` [3] in property `props`.
Danielo515
  • 2,933
  • 2
  • 19
  • 43
  • That's not the full error, it would be best to run flow at your CLI and paste the error in full. – Lyle Underwood Dec 23 '20 at 00:34
  • I'm confused by what the question is, seems like you should just be doing `type ItemType = Element` here as that's the only type of element you're actually creating. – Lyle Underwood Dec 23 '20 at 01:00
  • This is just a small reproduction of the actual problem. ItemType is a sum of the allowed item types, and Row is a wrapper component just for convenience, which is just returning one of the allowed types. In theory it should be something similar to a function that returns the wrapped component, and maybe that should be the way to go. – Danielo515 Dec 23 '20 at 10:34

1 Answers1

0

Running your code snippet on a project gave the following errors for the child components inside x

Cannot create `Parent` element because Could not decide which case to select, since case 1 [1] may work but if it doesn't case 2 [2] looks promising too. To fix add a type annotation to return [3].Flow(incompatible-type)

Assuming these are the errors you're getting, flow can't infer what the type of your components should be, so it wants you to manually annotate them. Adding return type of Node should do it

const Wrapper = (): Node => (
  <>
    <Foo disabled />
    <Bar />
  </>
);

const Defaults = (): Node => <Foo disabled={false} />;

const x = (
  <Parent>
    <Wrapper />
    <Wrapper />
    <Defaults />
  </Parent>
);

Though as a side note I'd strongly recommend you move to using import * as React from 'react'; so you can use React.Node instead. Otherwise Node from react will conflict with usage of html Node in the future.

Brianzchen
  • 629
  • 1
  • 15
  • Sorry for not putting the error message, my fault. The real error I'm getting is very close, but it is not like that. I updated the question with it. I tried adding the `Node` annotation, and also an specific annotation with only one of the allowed components and I get the same error. I tried reproducing the error on the REPL as best as I could, but since I don't understand it clearly it's easy to reproduce it – Danielo515 Dec 22 '20 at 11:44
  • I just added a simplified example that reproduces my problem 1:1 – Danielo515 Dec 22 '20 at 11:56