Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Property 'children' is missing in type

I am trying to setup Storybook with Typescript using babel-loader and ts-loader.

Everything works fine except using children in a React component:

[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'.

This is the .storybook/main.js file:

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;
  }
};

This is the index.stories.tsx file:

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>
);

And this is the implementation of 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;

Is there anything here I'm doing wrong?

like image 925
Erazihel Avatar asked Mar 24 '20 23:03

Erazihel


People also ask

Is missing in type TypeScript?

The TypeScript error "Property is missing in type but required in type" occurs when we do not set all of the properties an object of the specified type requires. To solve the error, make sure to set all of the required properties on the object or mark the properties as optional.

Is missing the following properties from type?

The error "Type is missing the following properties from type" occurs when the type we assign to a variable is missing some of the properties the actual type of the variable expects. To solve the error, make sure to specify all of the required properties on the object.

Is missing in type but required in type props?

The React. js error "Property is missing in type but required in type" occurs when we don't pass all of the required props to a component. To solve the error, make sure to pass all of the props the component requires, e.g. <MyComponent name="Tom" age={30} /> or mark its props as optional.

What has no properties in common with type IntrinsicAttributes?

js error "Type {children: Element} has no properties in common with type IntrinsicAttributes" occurs when we try to pass a children prop to a component that doesn't take any props. To solve the error define and type the props on the component.


2 Answers

One possible solution is to leverage the default children mechanism in functional components, React.FC, which lets you mount children without explicitly include them as a prop in your type definition. For your case this is achievable by applying the following changes:

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

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

Working sandbox for this

like image 188
gqstav Avatar answered Sep 18 '22 16:09

gqstav


step 1

add React.FC: it already comes with children declared for you. And add your custom Props inside the React's.

Your code should be this:

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

step 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;
}
like image 27
Tales Avatar answered Sep 18 '22 16:09

Tales