2
votes

I am starting out with TypeScript on a React app (next.js) and I'm not sure how to type React components.

I have a component like...

type Props = {
  children: JSX.Element;
};

export default function SiteLayout({ children }: Props): React.FC {
return (
  <div>
    {children}
  </div>
)

But this gives me the following error:

var children: JSX.Element
Type 'Element' is not assignable to type 'FC<{}>'.
Type 'Element' provides no match for the signature '(props: { children?: ReactNode; }, context?: any): ReactElement<any, any>'.ts(2322)

I also tried to get it working with simply using JSX.Element:

type Props = {
  children: JSX.Element;
};

export default function SiteLayout({ children }: Props): JSX.Element {

return (
  <div>
    {children}
  </div>
)

But this gives the following error in child components.

(alias) function SiteLayout({ children }: Props): JSX.Element import SiteLayout
This JSX tag's 'children' prop expects a single child of type 'Element', but multiple children were provided.ts(2746)

The above component is being consumed in by a Next.js page component like:

import Head from 'next/head';
import SiteLayout, { siteTitle } from '../../components/SiteLayout';

export default function myPage() {
  const pageTitle = 'My Page';


  return (
    <SiteLayout>
      <Head>
        <title>{siteTitle + ' - ' + pageTitle}</title>
      </Head>
      <div>
        content...
      </div>
    </SiteLayout>
  );
}

What is the correct approach? I'm confused when JSX.Element should be used and when React.FC should be.

2
Can you please share how you are consuming the component? React.FC cannot be the return type. Its variable type. Also the error says about children and not return typeRajesh
Thanks @Rajesh, I update my question. Is this enough info?Holly
unfortunately the question is closed and still don't get it. Anyone know of another forum where I can get help on this? A slack channel maybeHolly
children: JSX.Element; means you will have 1 child. You have more than one. Try Array<JSX.Element>Rajesh
Thank you @Rajesh, that answers my question. I also just tried children: JSX.Element | any; but Array<JSX.Element> is better. ThanksHolly

2 Answers

4
votes

The return type of the function is not a component, the function itself is component. That's why instead of

function SiteLayout({ children }: Props): React.FC { ...

It should be:

const SiteLayout: React.FC<Props> = ({ children }: Props) => {
    return (
      <div>
        {children}
      </div>
    );
}

Regarding the type of children prop, if there's no restriction on kind of children (string, boolean, element etc,) better to use ReactNode:

type Props = {
    children: React.ReactNode
}

Here's how it is defined.

0
votes

Your function is returning a React.FC type, which shouldnt be the case. The return type of function components is ReactNode, plus children are implicitly provided by the React.FC typing. If you explicitly type them, you can omit the React.FC and write:

const SiteLayout = ({children}: Props) => {
  return (
    <div>
      {children}
    </div>
  )
}