1

Is it possible to restrict passing a valid prop to a react component?

Example:

<SomeComponent primaryCTA={<Button size="small">Click here</Button} />

Now, in the code above, I want to user to NOT be able to provide size prop.

This is how type Props of SomeComponent look like

type SomeComponentProps = {
  primaryCTA: React.ReactElement<
     Exclude<ButtonProps, 'size'>,
     typeof Button>;
}

But, the code above doesn't work. You can still provide size prop to Button component inside SomeComponent.

1
  • Try setting size: never, in ButtonProps Commented Apr 14, 2021 at 18:28

1 Answer 1

1

You can't restrict the type here because rendered JSX doesn't carry with it the type of the component that rendered it. This means that there is no type information to restrict:

const button = <Button size="small">foo</Button> // type: JSX.Element

Instead, it's usually best to let SomeComponent handle creating the button by exposing props about how to do that.

For example, if primaryCTA was typed as string, then in your SomeComponent rendering you could create the button:

function SomeComponent({ primaryCTA }: Props) {
  return <Button size="small-or-whatever">{primaryCTA}</Button>
}

Or you can make primaryCTA be the type of props that Button expects.

You can use React.ComponentProps<typeof Button> to get the prop types from the Button component, and then you can use Omit<Props, 'size'> to remove whatever you don't want to expose. Lastly, you can spread those props back into the button with <Button {...primaryCTA} />

Putting that together, you could do something like:

interface SomeComponentProps {
    primaryCTA: Omit<React.ComponentProps<typeof Button>, 'size'>
}

function SomeComponent({ primaryCTA }: SomeComponentProps) {
    return <>
        <div>Testing this component</div>
        <Button {...primaryCTA} size='small' />
    </>
}

// Usage of SomeComponent
<SomeComponent primaryCTA={{ color: 'red', children: 'click here!' }} />

Playground

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.