Home > Enterprise >  What is the correct way to implement '...rest' in a TSX component?
What is the correct way to implement '...rest' in a TSX component?

Time:09-15

I want to implement ...rest in TSX components. According to TypeScript workaround for rest props in React, it should work. In the following app.tsx, a compiler warning occurs with the '<Container style=...' line:

import { ReactNode } from "react";

interface IParent {
  children?: ReactNode;
}

function Container({ children, ...rest }: IParent) {
  return <div {...rest}>{children}</div>;
}

export default function App() {
  return (
    <Container style={{ border: "1px solid red" }}>
      <h1>Hello World!</h1>
    </Container>
  );
}

Error:

Type '{ children: Element; style: { border: string; }; }' is not assignable to type 'IntrinsicAttributes & IParent'.
  Property 'style' does not exist on type 'IntrinsicAttributes & IParent'.ts(2322)

Sample: https://codesandbox.io/s/exciting-shirley-c0dwz5?file=/src/App.tsx

Is there a correct way to create components with ...rest? Thanks!

CodePudding user response:

The issue is that your IParent type says that only the children prop is allowed. If you want to allow all the props that divs allow, then you should make the type on your props like this:

import { HTMLAttributes } from 'react';

interface IParent extends HTMLAttributes<HTMLDivElement>{
  children?: ReactNode;
}

In fact, since div's already allow children of type ReactNode, you could remove that, and if there are no other props you can just do:

interface IParent extends HTMLAttributes<HTMLDivElement>{}

Or:

type IParent = HTMLAttributes<HTMLDivElement>

CodePudding user response:

The primary reason for using Typescript is to restrict types on your code. You still can use ...rest, but make sure you declare types on the interface properly like below

import type { ReactNode, CSSProperties } from "react";

interface IParent {
  children?: ReactNode;
  style?: CSSProperties; //declare style type
  title?: string; //fix your above error
}

function Container({ children, ...rest }: IParent) {
  return <div {...rest}>{children}</div>;
}

export default function App() {
  return (
    <Container style={{ border: "1px solid red" }} title="test">
      <h1>Hello World!</h1>
    </Container>
  );
}

Sandbox

  • Related