132

I'm missing something here with the validation how to add types validation? Having error "element 'children' implicitly has an 'any' type".

import * as React from 'react';
import Button from './Styles';

const Button1 = ({ children, ...props }) => (
  <Button {...props}>{children}</Button>
);

Button1.propTypes = {};

export default Button1;
Zahid Karim
  • 1,556
  • 3
  • 12
  • 14
  • @BoyWithSilverWings almost but not really, as that question is about propTypes and what the type should be, this one is about typescript and what causes this error. – Lukáš Gibo Vaic Mar 27 '19 at 08:12
  • Related answer in https://stackoverflow.com/questions/40745992/binding-element-index-implicitly-has-an-any-type/40746812#40746812 – Michael Freidgeim May 02 '20 at 23:22

12 Answers12

194

Edit 2022: with react 18, FC no longer provides children, so you have to type it yourself, and you can drop FC:

import React, { ReactNode } from "react";

interface Props {
    children?: ReactNode
    // any props that come into the component
}

const Button1 = ({ children, ...props }: Props) => (
    <Button {...props}>{children}</Button>
);

Yes you are missing a type for Props as whole, which means typescript sees it as any and your ts rules dont allow it.

You have to type your props as:

import React, { FC } from "react";

interface Props {
    // any props that come into the component
}

const Button1: FC<Props> = ({ children, ...props }) => (
    <Button {...props}>{children}</Button>
);
Lukáš Gibo Vaic
  • 3,960
  • 1
  • 18
  • 30
  • 4
    Why is this called IProps and not just Props? (I am brand new to TS, I am not challenging just asking). – Fasani Jul 19 '20 at 10:00
  • 7
    @FMD Its just naming, we used to type `I` in front of each name of interface, but with time we dont do that anymore. – Lukáš Gibo Vaic Jul 20 '20 at 12:11
  • Which imo is good to include, cuz sometimes we have a component with constants and such defined - the `I` for `Interface` in `IProps` etc. helps tell the difference. – Hari Reddy Aug 22 '22 at 21:30
38

This was a major issue for me and I wasted a lot of time figuring out the correct solution. Right now you have an error with the children prop but in the future, you might have this error for a lot of functions where you are destructuring the params. So I would suggest, follow this GitHub issue.

const yourfunc = ({destructuredProps}: {destructuredProps: type}) => {}
MANAN
  • 713
  • 9
  • 6
26

You can also add the predefined type to your functional components like this:

const Button1: React.FC<{}>  = ({ children }) => (
    <Button>{children}</Button>
);

By this way you don't have to repeat yourself to define children props.

The fuller version could be like this:

interface Props {
// any other props that come into the component, you don't have to explicitly define children.
}

const Button: React.FC<Props> = ({ children, ...props }) => {
  return (
      <Button {...props}>{children}</Button>
  );
};

Please note it works for React 16.8

Akshay Vijay Jain
  • 13,461
  • 8
  • 60
  • 73
Hung Ton
  • 381
  • 3
  • 5
17

As another approach, you can use the built-in generic type "React.PropsWithChildren" for children in props, taking those props accordingly. A very short code would look like this:

import React from "react";
import Button from "./Styles";

type MyComponentProps = React.PropsWithChildren<{}>;

export default function MyComponent({ children, ...other}: MyComponentProps) {
  return <Button {...other}>{children}</Button>;
}
9

You can use types as well

type ButtonProps = {
    children: ReactNode;
    
}

const Button = ({ children }: ButtonProps) => (
    <button>{children}</button>
);
6

I find it best to have the component props interface extend from React.HTMLAttributes because it gives you the standard HTML attributes without any extra configuration:

interface Button1Props extends React.HTMLAttributes<Element> {
  // add any custom props, but don't have to specify `children`
}

const Button1 = ({ children, ...props }: Button1Props) => (
    <Button {...props}>{children}</Button>
)

If you want to enforce children to be provided, you can make it required by redefining it in the props interface:

interface Button1Props extends React.HTMLAttributes<Element> {
  children: React.ReactNode
  // add any custom props, but don't have to specify `children`
}

const Button1 = ({ children, ...props }: Button1Props) => (
    <Button {...props}>{children}</Button>
)
Merott
  • 7,189
  • 6
  • 40
  • 52
6

It needs 'any' so give it !

const Button1 = ({ children, ...props } : any)

Then handle it in function if you want to preserve the type

idris
  • 291
  • 3
  • 7
3

Also do this to stop error: children?: React.ReactNode;

export interface props {
    children?: React.ReactNode; }

const Screen = ({ children }: props) => {
    return (
        <div style={{ margin: '2%' }}>
            {children}
        </div>
    ); };

export default Screen;
Pickachu
  • 29
  • 2
1

This error can be fixed by explicitly defining type for the variable (children in this case) and not leaving it to be implicitly inferred

Error can be stopped altogether with TypeScript --noImplicitAny compiler option

Akshay Vijay Jain
  • 13,461
  • 8
  • 60
  • 73
0

One answer I found and wanted to share, but will probably be highly frowned upon, is that you can set skipLibCheck to true in your tsconfig.json within the compilerOptions object, and it will ignore the issue.

As a caveat, please ensure you know what you are doing when adding this rule. A good article about this is here: https://www.testim.io/blog/typescript-skiplibcheck/

E_net4
  • 27,810
  • 13
  • 101
  • 139
Awyssa
  • 116
  • 6
0

Not specifically due to this issue, but related to it, because of the children prop: The usage of React.FC discouraged and by now is officially removed from from Typescript template. https://github.com/facebook/create-react-app/pull/8177

Janos
  • 650
  • 8
  • 13
0

Write this code, it shoud fix your problem: enter image description here

Demna
  • 1
  • 1