Как использовать детей с функциональным компонентом React Stateless в TypeScript?

Используя TypeScript с React, нам больше не нужно расширять React.Props, чтобы компилятор знал, что все реквизиты компонентов компонента могут иметь дочерние элементы:

interface MyProps { }

class MyComponent extends React.Component<MyProps, {}> {
  public render(): JSX.Element {
    return <div>{this.props.children}</div>;
  }
}

Тем не менее, это не похоже на функциональные компоненты без состояния:

const MyStatelessComponent = (props: MyProps) => {
  return (
    <div>{props.children}</div>
  );
};

Выдает ошибку компиляции:

Ошибка: (102, 17) TS2339: свойство 'children' не существует по типу 'MyProps'.

Я предполагаю, что это связано с тем, что компилятор действительно не знает, что в аргументе реквизита будет дана функция ваниль children.

Итак, вопрос в том, как мы должны использовать детей в функциональном компоненте без состояния в TypeScript?

Я мог бы вернуться к старому способу MyProps extends React.Props, но интерфейс Props отмечен как устаревший, а компоненты без гражданства - У меня есть или поддерживаю Props.ref, насколько я понимаю.

Итак, я могу определить children prop вручную:

interface MyProps {
  children?: React.ReactNode;
}

Во-первых: ReactNode правильный тип?

Во-вторых: я должен писать дети как необязательные (?), иначе потребители будут считать, что children должен быть атрибутом компонента (<MyStatelessComponent children={} />) и поднять ошибку, если не предоставляется значение.

Кажется, что я чего-то не хватает. Может ли кто-нибудь дать некоторую ясность относительно того, может ли мой последний пример использовать функциональные компоненты без состояния с детьми в React?

Ответ 1

Обновление React 16.8: Начиная с React 16.8, имена React.SFC и React.StatelessComponent запрещены. На самом деле, они стали псевдонимами React.FunctionComponent типа или React.FC для краткости.

Вы бы использовали их так же, хотя:

const MyStatelessComponent : React.FunctionComponent<MyProps> = props =>
    <div>
        <p>{props.propInMyProps}</p>
        <p>{props.children}</p>
    </div>

Перед Реакцией 16.8 (Старее):

На данный момент вы можете использовать React.StatelessComponent<>, так как:

const MyStatelessComponent : React.StatelessComponent<{}> = props =>
    <div>{props.children}</div>

Что я добавил там, так это установил тип возвращаемого компонента для типа React.StatelessComponent.

Для компонента с вашими собственными опорами (например, интерфейс MyProps):

const MyStatelessComponent : React.StatelessComponent<MyProps> = props =>
    <div>
        <p>{props.propInMyProps}</p>
        <p>{props.children}</p>
    </div>

Теперь, props получил children собственности, а также те из MyProps интерфейса.

Я проверил это в машинописной версии 2.0.7

Кроме того, вы можете использовать React.SFC вместо React.StatelessComponent для краткости.

Ответ 2

Вы можете использовать React.PropsWithChildren<P> для своих реквизитов:

interface MyProps { }

function MyComponent(props: React.PropsWithChildren<MyProps>) {
  return <div>{props.children}</div>;
}