gpt4 book ai didi

reactjs - 根据传递的组件推断 Prop 类型也作为 Prop

转载 作者:行者123 更新时间:2023-12-05 03:56:49 27 4
gpt4 key购买 nike

是否可以从也作为 prop 传递的未知组件推断出正确的 props 类型?

如果已知组件(存在于当前文件中),我可以获得 Prop :

type ButtonProps = React.ComponentProps<typeof Button>;

但是如果我想创建一个通用组件 Box接受 as 中的组件prop 和组件的 props 在 props 中支柱。组件可以添加一些默认的 Prop ,有一些行为,没关系。基本上它类似于高阶组件,但它是动态的。

import React from "react";

export interface BoxProps<TComponent> {
as?: TComponent;
props?: SomehowInfer<TComponent>; // is it possible?
}

export function Box({ as: Component, props }: BoxProps) {
// Note: it doesn't have to be typed within the Box (I can pass anything, I can control it)
return <Component className="box" title="This is Box!" {...props} />;
}

function MyButton(props: {onClick: () => void}) {
return <button className="my-button" {...props} />;
}

// usage:

function Example() {
// I want here the props to be typed based on what I pass to as. Without using typeof or explicitly passing the generic type.
return (
<div>
<Box
as={MyButton}
props={{
onClick: () => {
console.log("clicked");
}
}}
>
Click me.
</Box>
</div>
);
}

要求:

  • 必须在不传递通用类型的情况下工作(这可能吗?),因为它几乎无处不在
  • 必须使用用户定义的组件 ( React.ComponentType<Props> )
  • 如果它也适用于 react html 元素(a、按钮、链接……它们有不同的属性),那就太好了,但不是必需的

最佳答案

您可以使用预定义的 react 类型 ComponentProps 从组件类型中提取 Prop 类型。

import React from "react";

export type BoxProps<TComponent extends React.ComponentType<any>> = {
as: TComponent;
props: React.ComponentProps<TComponent>;
}

export function Box<TComponent extends React.ComponentType<any>>({ as: Component, props }: BoxProps<TComponent>) {
return <div className="box" title="This is Box!">
<Component {...props} />;
</div>
}

function MyButton(props: {onClick: () => void}) {
return <button className="my-button" {...props} />;
}

// usage:

function Example() {
// I want here the props to be typed based on what I pass to as. Without using typeof or explicitly passing the generic type.
return (
<div>
<Box
as={MyButton}
props={{ onClick: () => { } }}
></Box>
</div>
);
}

Playground Link

根据您的具体用例,解决方案可能会有所不同,但基本思想是相似的。例如,您可以稍微改变类型并将 Prop 作为 BoxProps 的类型参数。这样你就可以限制组件 Prop 具有一些你可以在 Box 组件内提供的特定属性:

export type BoxProps<TProps extends {title: string}> = {
as: React.ComponentType<TProps>;
} & {
props: Omit<TProps, 'title'>;
}

export function Box<TProps extends {title: string}>({ as: Component, props }: BoxProps<TProps>) {
return <div className="box" title="This is Box!">
<Component title="Title from box" {...props as TProps} />;
</div>
}

Playground Link

如果想接受内在标签,也可以在TComponent约束中加入keyof JSX.IntrinsicElements:

export type BoxProps<TComponent extends React.ComponentType<any> | keyof JSX.IntrinsicElements> = {
as: TComponent;
props: React.ComponentProps<TComponent>;
}

export function Box<TComponent extends React.ComponentType<any>| keyof JSX.IntrinsicElements>({ as: Component, props }: BoxProps<TComponent>) {
return <div className="box" title="This is Box!">
<Component {...props} />;
</div>
}

Playground Link

关于reactjs - 根据传递的组件推断 Prop 类型也作为 Prop ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59054141/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com