Свойство 'children' отсутствует в типе - PullRequest
1 голос
/ 25 марта 2020

Я пытаюсь настроить Storybook с Typescript, используя babel-loader и ts-loader .

Все отлично работает, кроме использования children в компоненте React :

[tsl] ERROR in .../stories/index.stories.tsx(8,56)
      TS2769: No overload matches this call.
      Property 'children' is missing in type '{ title: string; }' but required in type 'Props'.

Это файл .storybook/main.js:

module.exports = {
  addons: [
    "@storybook/addon-knobs",
  ],
  stories: ["../packages/**/*.stories.tsx"],
  webpackFinal: async config => {
    config.module.rules.push({
      test: /\.(ts|tsx)$/,
      exclude: /node_modules/,
      use: [
        {
          loader: require.resolve('ts-loader')
        },
        {
          loader: require.resolve('babel-loader'),
          options: {
            presets: [
              "@babel/preset-env",
              "@babel/preset-react"
            ]
          }
        }
      ],
    });

    config.resolve.extensions.push('.ts', '.tsx');

    return config;
  }
};

Это файл index.stories.tsx:

import React from "react";

import Collapsible from "../src";

export default {
  title: "Collapsible"
};

const content = <span>Content</span>;

export const simpleCollapsible = () => (
  <Collapsible title="Collapsible">{content}</Collapsible>
);

И это реализация Разборный:

import React, { ReactNode, useState } from "react";
import styled, { ThemeProvider } from "styled-components";
import {
  BorderProps,
  ColorProps,
  FlexboxProps,
  LayoutProps,
  SpaceProps,
  TypographyProps
} from "styled-system";
import Theme from "@atw/theme";

import { KeyboardArrowDown } from "@styled-icons/material";

import Box from '~/box';
import Button from '~/button';

interface Props
  extends BorderProps,
    ColorProps,
    FlexboxProps,
    LayoutProps,
    SpaceProps,
    TypographyProps {
  children: ReactNode;
  title: string;
}

const Collapsible = ({ children, title, ...rest }: Props) => {
  const [isCollapsed, setIsCollapsed] = useState(false);

  const handleCollapse = () => {
    setIsCollapsed(!isCollapsed);
  };

  return (
    <ThemeProvider theme={Theme}>
      <Button
        border="none"
        padding={0}
        marginBottom={2}
        width={1}
        textAlign="start"
        onClick={handleCollapse}
        {...rest}
      >
        <IconBox isCollapsed={isCollapsed}>
          <KeyboardArrowDown size="24px" />
        </IconBox>
        {title}
      </Button>
      {!isCollapsed && (
        <Box display="flex" flexDirection="column">
          {children}
        </Box>
      )}
    </ThemeProvider>
  );
};

export default Collapsible;

Что-то здесь я делаю не так?

Ответы [ 3 ]

1 голос
/ 28 марта 2020

Одним из возможных решений является использование механизма дочерних элементов по умолчанию в функциональных компонентах React.FC, который позволяет монтировать дочерние элементы без явного включения их в качестве опоры в определение типа. Для вашего случая это достижимо путем применения следующих изменений:

interface Props
  extends BorderProps,
    ColorProps,
    FlexboxProps,
    LayoutProps,
    SpaceProps,
    TypographyProps {
  title: string;
}

const Collapsible: React.FC<Props> = ({ children, title, ...rest }) => {
  ...
};

Рабочая песочница для этого

1 голос
/ 28 марта 2020

шаг 1

добавить React.F C: он уже поставляется с детьми, объявленными для вас. И добавьте свой собственный реквизит в React's.

Ваш код должен быть таким:

const Collapsible : React.FC<Props> = ({ children, title, ...rest }) => {

шаг 2

interface Props extends BorderProps,
    ColorProps,
    FlexboxProps,
    LayoutProps,
    SpaceProps,
    TypographyProps {
  children: ReactNode; // as React.FC declares it for you, just delete this line
  title: string;
}

шаг 3

нет шага 3:)

0 голосов
/ 28 марта 2020

Я добавил Babel Preset Typescript и ошибка исчезла.

Вот как выглядит мой .storybook/main.js:

module.exports = {
  addons: [
    "@storybook/addon-knobs",
  ],
  stories: ["../packages/**/*.stories.tsx"],
  webpackFinal: async config => {
    config.module.rules.push({
      test: /\.(ts|tsx)$/,
      exclude: /node_modules/,
      use: [
        {
          loader: require.resolve('ts-loader'),
          options: {
            configFile: '../tsconfig.json',
            transpileOnly: true
          }
        },
        {
          loader: require.resolve('babel-loader'),
          options: {
            presets: [
              "@babel/preset-env",
              "@babel/preset-react",
              "@babel/preset-typescript"
            ]
          }
        }
      ],
    });

    config.resolve.extensions.push('.ts', '.tsx');

    return config;
  }
};
...