Правильный тип потока для метода рендеринга React?

Мне любопытно, какова собственно аннотация потока Flow для обоих методов render в классах React и простой return в функции без состояния:

const UserProfilePage = () => {
  return <div className="container page">
    <UserProfileContainer />
  </div>
};

Устанавливая тип возврата преднамеренно неверным (на число), я получил эту ошибку:

  8:   return <div className="container page">
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ React element: 'div'
  8:   return <div className="container page">
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ React$Element. This type is incompatible with the expected return type of
  7: const UserProfilePage = (): number => {
                                 ^^^^^^ number

Таким образом, изменение кода на это, похоже, удовлетворяет Flow:

const UserProfilePage = (): React$Element => {
  return <div className="container page">
    <UserProfileContainer />
  </div>
};

Мне интересно, правильно ли это, и если да, то где это документировано?

Ответ 1

Вам не нужно комментировать метод рендеринга, Flow должен иметь возможность выводить тип вывода, потому что он знает, что JSX desugars.

Flow имеет встроенный интерфейс React, в котором определяется весь этот материал:

declare class React$Element<Config> {
  type: ReactClass<Config>;
  props: $PropsOf<Config>;
  key: ?string;
  ref: any;
}

А потом

render(): ?React$Element<any>;

Поэтому, если вы хотите предоставить явный тип возвращаемого метода рендеринга, вы можете использовать эту подпись. Ну, может быть, без вопросительного знака, если вы знаете, что не возвращаете null. Не уверен, есть ли эффект для удаления <any>.

Ответ 2

Согласно документации Flow: React: Type Reference, правильный тип React.Node:

import * as React from 'react';

class MyComponent extends React.Component<{}> {
  render(): React.Node {
    // ...
  }
}

Это представляет любой узел, который может быть отображен в приложении React. React.Node может быть неопределенным, нулевым, логическим, числом, строкой, элементом React или массивом любого из этих типов рекурсивно.

Если вам нужен тип возврата для методов компонента render() или вам нужен общий тип для поддержки детей, тогда вы должны использовать React.Node.

Однако примеры в документации обычно не выписывают тип render() явно. Они только выписывают React.Component и тип реквизита, например:

import * as React from 'react';

type Props = {
  foo: number,
  bar?: string,
};

class MyComponent extends React.Component<Props> {
  render() {
    return <div>{this.props.bar}</div>;
  }
}

Это связано с тем, что расширение React.Component автоматически сообщает Flow, что должен вернуть метод render().