I am trying to create a React component in TypeScript, and I want to have a dynamic component that will wrap each of the child nodes that are passed to my component. The component is called Slider
and here’s how I want it to work:
- Children are passed to the component
<Slider wrapper='div'>
<p>Slide 1</p>
<p>Slide 2</p>
<p>Slide 3</p>
</Slider>
- Component logic wraps each child node in whatever component/string passed to the
Slider
component. If you pass:
<Slider wrapper='div'>...</Slider>
You’ll get:
<div>
<p>Slide 1</p>
</div>
And if you pass:
<Slider wrapper={MyComponent}>...</Slider>
You’ll get:
<MyComponent>
<p>Slide 1</p>
</MyComponent>
I wanted to be able to accept all the props within the component and then render everything with logic inside the component, but I keep getting a Typescript error:
Type
{ children: ReactNode; }
has no properties in common with typeIntrinsicAttributes
. ts(2559)
I’ve looked at some other Stack Overflow questions and some Github issues, but I haven’t found solutions that help with my problem. I could certainly be overthinking or glossing over something obvious, so whatever help you can offer, I’m willing to hear!
Here’s my component code so far:
import { PropsWithChildren, ReactElement, ReactNode } from "react";
type SliderProps = PropsWithChildren<{
wrapper?: string | (() => ReactElement);
}>;
export default function Slider({
children,
wrapper: Wrapper = "div",
}: SliderProps) {
return <Wrapper>{children}</Wrapper>; // error on this line under <Wrapper>
}
3
Answers
I don’t think you can just swap out a string for a component. I believe this is more appropriate.
TypeScript expects the wrapper prop to be a string that refers to an HTML element or a React component type, but it’s not able to infer the correct type for
Wrapper
when you try to use it as a component.To fix this, you can define the wrapper prop to be of type
React.ElementType
, which is a built-in type that React provides for representing a component that can be rendered.Here’s how you can adjust your
SliderProps
type and Slider component:You just need to use a more specific type than string so the compiler knows it’s limited to valid HTML tag names:
Note that the Typescript
JSX
namespace is ambient, you don’t have to import it as long as you’ve imported React itself.Playground