Search code examples
reactjsreact-propsreact-functional-component

Can't pass props like className or style to custom component's props


I'm working on creating a TypeScript friendly NPM package but I'm having trouble passing common HTML attributes as props like className and style to my component. I was hoping to not have to manually add each attribute to my list of props by extending an interface with all the desired props. My simplified component looks like this:

import React, { Key, ReactElement } from "react";

interface MyComponentProps extends React.HTMLAttributes<HTMLDivElement> {
    customText: string;
    uniqueKey?: Key;
}

export function MyComponent({uniqueKey, customText, ...props}: MyComponentProps): ReactElement {
    return (
        <div key={uniqueKey} {...props}>{customText}</div>
    );
}

I created a uniqueKey prop since it can't be named just key (same with ref). I tried to expand a props parameter to pass arbitrary props to my component, but it doesn't seem to make a difference. I import this component into my project and try to call it like:

<MyComponent customText="Hello World" uniqueKey={123} className="myClass" />

I get the error: Property 'className' does not exist on type 'MyComponentProps'.

I was hoping this would work since MyComponentProps extends HTMLAttributes which has the props I want like className and style.

My index.d.ts file looks like:

import React, { Key, ReactElement } from "react";
interface MyComponentProps extends React.HTMLAttributes<HTMLDivElement> {
    customText: string;
    uniqueKey?: Key;
}
export declare function MyComponent({ uniqueKey, customText, ...props }: MyComponentProps): ReactElement;
export {};

Solution

  • The easiest way to get the available props for a specific HTML element is by using JSX.IntrinsicElements.

    type MyComponentProps = JSX.IntrinsicElements['div'] & {
        customText: string;
        uniqueKey?: Key;
    }
    

    Under the hood, JSX.IntrinsicElements['div'] is the following type.

    React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>