ediblecode
ediblecode

Reputation: 11971

How to specify return type as a list of React components with Flow

I've seen elsewhere people using React$Element<Type> so I assumed that to return an array of those would be as simple as adding [] to the end. I've tried that here:

navbarItems: INavbarItem[];

getNavbarItems(): React$Element<NavbarItem>[] {
  return this.navbarItems.map((navbarItem, index) => {
    return (
      <NavbarItem
        key={index}
        title={navbarItem.title}
        icon={navbarItem.icon}
        listPath={navbarItem.listPath}
        createPath={navbarItem.createPath}
      />
    );
  });
}

NavbarItem

class NavbarItem extends Component<Props, any> {
  constructor(props: Props) {
    super(props);
    /* stuff */
  }

  /* Couple of functions */

  render() {
    return (
      <li>
        <DropdownTitle/>
        {this.state.open && (
          <ul>
            <MenuItem>List</MenuItem>
            <MenuItem>Create</MenuItem>
          </ul>
        )}
      </li>
    );
  }
}

However, when I run flow I get the following error:

Cannot return this.navbarItems.map(...) because statics of NavbarItem [1] is incompatible with NavbarItem [2] in type argument ElementType [3] of array element.

[1] class [NavbarItem] extends Component

[2] getNavbarItems(): React$Element<[NavbarItem]>[]

[3] declare type React$Element<+[ElementType]: React$ElementType> (from react.js)

[] above denotes where the ^ are pointing at in the error message. Being new to flow I'm unsure what it means by the statics of my Component here.

Upvotes: 2

Views: 5571

Answers (1)

James Kraus
James Kraus

Reputation: 3478

First, you should also probably be using the React.Element<typeof Component> type instead of React$ElementType<T>, since the latter is supposed to be internal. The documentation for React.Element<typeof Component> also hints that you need to use the typeof operator to specify you mean the type of the NavbarItem class:

(Try)

import * as React from 'react'

// ...

class Foo {
   navbarItems: INavbarItem[];

  getNavbarItems(): React.Element<typeof NavbarItem>[] {
    return this.navbarItems.map((navbarItem, index) => {
      return (
        <NavbarItem
          key={index}
          title={navbarItem.title}
          icon={navbarItem.icon}
          listPath={navbarItem.listPath}
          createPath={navbarItem.createPath}
        />
      );
    });
  }
}

This still works if you use React$ElementType<T>:

(Try)

class Foo {
   navbarItems: INavbarItem[];

  getNavbarItems(): React$Element<typeof NavbarItem>[] {
    return this.navbarItems.map((navbarItem, index) => {
      return (
        <NavbarItem
          key={index}
          title={navbarItem.title}
          icon={navbarItem.icon}
          listPath={navbarItem.listPath}
          createPath={navbarItem.createPath}
        />
      );
    });
  }
}

Upvotes: 3

Related Questions