我有一个关于在React组件中作为道具传递的类型检查的问题:我们如何做类型检查以确保我们作为道具只允许组件传递?
让我举例说明。我们有想要传递的组件:
type DummyProps = {
name: string;
};
const Dummy = ({ name }: DummyProps) => {
return (<div>{name}</div>);
}
以及我们想要注入Dummy
组件的组件(并且具有静态类型检查,因此我们不能传递任何其他类型):
type DummyWrapperProps = {
dummy: ReactComponentElement<typeof Dummy>;
};
const DummyWrapper = ({ dummy }: DummyProps) => {
return (<div>{name}</div>);
}
现在,如果我们调用DummyWrapper
,尽管已经显式地将其dummy
道具的类型设置为ReactComponentElement<typeof Dummy>
,似乎我们可以传递任何ReactElement,无论它具有什么道具/类型:
const dummyElement = <Dummy name='dummy' />
const otherElement = <Other /> //this component is defined elsewhere
<DummyWrapper dummy={dummyElement} /> // This works
<DummyWrapper dummy={otherElement} /> // This also works
我也尝试过做类似的事情,让DummyWrapperProps
与React.ReactElement
,React.FC
等一起定义,但总是得到相同的结果:typescript静态类型检查不会警告传递的组件/元素不匹配预期类型。
我认为这个问题也延伸到children
,因为它基本上是相同的事情:你正在传递元素。
最后,我知道我可以做一些动态类型检查,读取组件正在接收的节点的属性,但是正如我说的,我想在编译时做类型检查。
我认为,你不能这样做,因为任何元素实例化类型都将是JSX.Element
也许你可以这样做:
const DummyWraper = ({ dummy: D, name }: { dummy: FC<DummyProps> } & DummyProps) => (
<div>
<D name={name} />
</div>
)
产生:
type DummyProps = {
name: string
}
const Other: FC<{ some: number }> = () => <div>1</div>
const Dummy: FC<DummyProps> = ({ name }) => {
return <div>{name}</div>
}
const dummyElement = <Dummy name="dummy" />
const otherElement = <Other />
const b = <DummyWraper dummy={Other} name="dummy" />
const c = <DummyWraper dummy={Dummy} name="dummy" />
注意Other
的FC<{}>
类型,因为typescript中的{}
和对象的any
一样工作