gpt4 book ai didi

javascript - 如何使用附加接口(interface)定义通用 HOC 以添加到 props

转载 作者:行者123 更新时间:2023-12-05 03:21:42 25 4
gpt4 key购买 nike

我需要创建一个通用的 HOC,它将接受一个将被添加到组件 props 的接口(interface)。

我实现了以下功能,但它需要两个参数而不是一个。我想从传递给函数的组件中获取第二个参数。

export const withMoreProps = <NewProps, Props>(WrappedComponent: React.FC<Props>): React.FC<Props & NewProps> => {
const displayName = WrappedComponent.displayName || WrappedComponent.name || 'Component';

const ComponentWithMoreProps = (props: Props & NewProps) => <WrappedComponent {...props} />;

ComponentWithMoreProps.displayName = `withMoreProps(${displayName})`;

return ComponentWithMoreProps;
};

目前当我尝试使用它时:

const Button = (props: { color: string }) => <button style={{ color: props.color }}>BTN</button>;

export const Button2 = withMoreProps<{ newProperty: string }>(Button);

我收到此错误消息

Expected 2 type arguments, but got 1.

它应该像 styled-components 一样工作,您只能在其中定义额外的 Prop 。

export const StyledButton = styled(Button)<{ withPadding?: boolean }>`
padding: ${({ withPadding }) => (withPadding ? '8px' : 0)};
`;

编辑:

这是我在应用程序中创建的 HOC 的简化版本。真正的 HOC 要复杂得多,并且会做其他事情,但为了简化起见,我制作了这个示例以仅关注我遇到的问题。

最佳答案

一般来说,您要使用infer 关键字。您可以阅读更多相关信息 here ,但简而言之,您可以将其视为从泛型类型中“提取”类型的助手。

让我们定义一个类型,从 React 组件中提取 prop 类型。

type InferComponentProps<T> = T extends React.FC<infer R> ? R : never;

它做什么的例子:

const Button = (props: { color: string }) => <button style={{ color: props.color }}>BTN</button>;
type ButtonProps = InferComponentProps<typeof Button>; // hover over ButtonProps, see {color: string}

现在我们有了这个“助手类型”,我们可以继续实现您想要的东西了——但是我们确实遇到了一个问题。在 typescript 中调用泛型函数时,有些类型不能指定,有些则不能。您要么指定与此函数调用匹配的所有具体类型,要么不指定任何类型,然后让 Typescript 找出类型。

function genericFunction<T1, T2>(t1: T2) {
//...
}
const a = genericFunction('foo') //ok
const b = genericFunction<number, string>('foo') //ok
const c = genericFunction<string>('foo') //error

您可以跟踪 typescript 问题 here .


因此,为了解决这个问题,我们需要对您的代码做一个小改动,并执行一个返回新组件的函数。如果您注意到,这正是 styled 的工作方式,因为使用标记的模板文字实际上是一个函数调用。因此,您在上面发布的样式化组件代码中有 2 个函数调用。

所以最终的代码看起来是这样的:

export const withMoreProps =
<C extends React.FC<any>>(WrappedComponent: C) =>
<NewProps extends Object>(): React.FC<InferComponentProps<C> & NewProps> => {
const displayName = WrappedComponent.displayName || WrappedComponent.name || 'Component';

//need to re-type the component
let WrappedComponentNew = WrappedComponent as React.FC<InferComponentProps<C> & NewProps>;

const ComponentWithMoreProps = (props: InferComponentProps<C> & NewProps) => <WrappedComponentNew {...props} />;

ComponentWithMoreProps.displayName = `withMoreProps(${displayName})`;

return ComponentWithMoreProps;
};

const Button = (props: { color: string }) => <button style={{ color: props.color }}>BTN</button>;

export const Button2 = withMoreProps(Button)<{ newProperty: string }>(); //Notice the function call at the end

关于javascript - 如何使用附加接口(interface)定义通用 HOC 以添加到 props,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72897772/

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