简体   繁体   English

Typescript - 限制将有效道具传递给 React 组件

[英]Typescript - Restrict passing valid prop to a React component

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.现在,在上面的代码中,我希望用户不能提供size道具。

This is how type Props of SomeComponent look like这就是 SomeComponent 的类型 Props 的样子

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.您仍然可以为 SomeComponent 中的 Button 组件提供 size 属性。

You can't restrict the type here because rendered JSX doesn't carry with it the type of the component that rendered it.你不能在这里限制类型,因为渲染的 JSX 不携带渲染它的组件的类型。 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.相反,通常最好让SomeComponent通过公开有关如何执行此操作的道具来处理创建按钮。

For example, if primaryCTA was typed as string , then in your SomeComponent rendering you could create the button:例如,如果primaryCTA键入为string ,那么在SomeComponent渲染中您可以创建按钮:

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.或者,您可以将primaryCTA设为Button期望的道具类型。

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.您可以使用React.ComponentProps<typeof Button>Button组件中获取道具类型,然后可以使用Omit<Props, 'size'>删除您不想公开的任何内容。 Lastly, you can spread those props back into the button with <Button {...primaryCTA} />最后,您可以使用<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 操场

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM