Javascript 正确键入返回forwardRef组件的HOC组件
我正在尝试创建一个HOC,它返回一个带有forwardRef的组件,但不确定如何键入它 这是密码Javascript 正确键入返回forwardRef组件的HOC组件,javascript,reactjs,typescript,higher-order-components,react-forwardref,Javascript,Reactjs,Typescript,Higher Order Components,React Forwardref,我正在尝试创建一个HOC,它返回一个带有forwardRef的组件,但不确定如何键入它 这是密码 type Omitted = 'variant' | 'size'; export interface InputProps<T extends Omit<T, Omitted>> { startIcon?: React.ReactElement; endIcon?: React.ReactElement; } const withInput = <
type Omitted = 'variant' | 'size';
export interface InputProps<T extends Omit<T, Omitted>> {
startIcon?: React.ReactElement;
endIcon?: React.ReactElement;
}
const withInput = <P extends object>(InputComponent: React.ComponentType<P>) =>
React.forwardRef<HTMLInputElement, InputProps<P>>(
({ startIcon, endIcon, ...props }, ref) => {
return (
<InputGroup>
{startIcon && (
<InputLeftElement>
{startIcon}
</InputLeftElement>
)}
<InputComponent ref={ref} {...props} />
{endIcon && (
<InputRightElement>
{endIcon}
</InputRightElement>
)}
</InputGroup>
);
}
);
const Input = withInput(InputBaseComponent);
Input.Number = withInput(NumberInputBaseComponent);
另一个在Input.Number上
Property 'Number' does not exist on type 'ForwardRefExoticComponent<InputProps<Pick<InputProps, "variant" | "size" | "left" | "right" | "form" | "p" | "slot" | "style" | "title" | "pattern" | "ref" | "key" | "sx" | "accept" | "alt" | "autoComplete" | ... 514 more ... | "isLoading"> & Pick<...>> & RefAttributes<...>>'.
类型“ForwardRefExoticComponent”上不存在属性“Number”。
如果有人想试用,这里有一个指向codesandbox的链接:属性“Number”不存在
Input.Number
错误更容易理解。您正试图导出一个对象,该对象是一个组件,并且其属性<代码>编号代码>是另一个组件。错误告诉您不能在组件上设置任意属性,如Number
,这有点道理(这是可行的,但很复杂)。我建议将Base
和Number
放在同一个级别,而不是将其中一个作为另一个的属性
const Input = {
Base: withInput(InputBaseComponent),
Number: withInput(NumberInputBaseComponent)
}
现在,Input
只是一个具有两个不同组件作为属性的对象
export type InputProps<T> = Omit<T, Omitted> & {
startIcon?: React.ReactElement;
endIcon?: React.ReactElement;
}
您还可以单独导出各种实例,并在通过执行以下操作导入时将它们分组在一起
import * as Input from `./Input`
将…道具分配给“P”
首先,我认为你的InputProps
接口没有达到你想要的效果
export interface InputProps<T extends Omit<T, Omitted>> {
startIcon?: React.ReactElement;
endIcon?: React.ReactElement;
}
这更好,因为现在我们在…props
中有了一些实际的道具。在它上面盘旋显示
Pick<React.PropsWithChildren<InputProps<P>>, "children" | Exclude<Exclude<keyof P, Omitted>, "startIcon" | "endIcon">>
类型安全
可以说,…道具是p
?当我们将用作
时,我们基本上是在告诉typescript闭嘴,因为我们知道的比它多。所以我们要确保我们没有给它提供坏信息
什么时候{…props}不能分配给p
?我们如何防止这些情况发生
这里有一些值得关注的原因,因为我们从内部组件的道具中省略了变量和大小,所以typescript知道…道具(我们希望是p
)不包含这两个属性。如果这些属性存在于类型P
上并且是必需的,则…props
不能是P
。如果P
包含所需的属性startIcon
和endIcon
,则情况也是如此,因为我们将这些属性与排列一起取出
对于variant
和size
,我真的不认为省略它们有什么意义。您没有为它们设置任何默认值,为什么不让它们通过呢
但是作为一个总体想法,对于startIcon
和endIcon
,我们需要改进p扩展
,以便如果p
具有这些属性,它们必须是可选的。我们还希望确保我们的InputComponent
能够接受我们正在传递的ref
类型
如果您对以下类型进行细化,您会更加确信我们所断言的as
是准确的:
interface Dropped {
variant?: any;
size?: any;
}
interface Icons {
startIcon?: React.ReactElement;
endIcon?: React.ReactElement;
}
export type InputProps<T> = Omit<T, keyof Dropped | "ref"> & Icons;
type PBase = {
ref?: React.Ref<HTMLInputElement>;
} & Dropped & Partial<Record<keyof Icons, any>>
const withInput = <P extends PBase>(InputComponent: React.ComponentType<P>) => ....
接口已删除{
变体?:任何;
尺寸?:任何尺寸;
}
界面图标{
startIcon?:React.ReactElement;
endIcon?:React.ReactElement;
}
导出类型InputProps=省略图标(&I);
类型PBase={
ref?:React.ref;
}已删除和部分(&D)
常量withInput=(InputComponent:React.ComponentType
)=>。。。。
<InputComponent {...props as P} ref={ref} />
interface Dropped {
variant?: any;
size?: any;
}
interface Icons {
startIcon?: React.ReactElement;
endIcon?: React.ReactElement;
}
export type InputProps<T> = Omit<T, keyof Dropped | "ref"> & Icons;
type PBase = {
ref?: React.Ref<HTMLInputElement>;
} & Dropped & Partial<Record<keyof Icons, any>>
const withInput = <P extends PBase>(InputComponent: React.ComponentType<P>) => ....