这是场景:
我有一个自定义组件:
class MyComponent extends React.Component {
render () {
return (
<SuperComponent>
<SubComponent1 /> // <- valid child
</SuperComponent>
)
}
class MyComponent extends React.Component {
render () {
return (
<SuperComponent>
<SubComponent2 /> // <- No! It's not right shape
</SuperComponent>
)
}
以及引用的SuperComponent和SubComponent1是:
interface superPropsType = {
children: ReactElement<subPropsType1>
}
class SuperComponent extends React.Component<superPropsType> { ... }
interface subPropsType1 = {
name: string
}
class SubComponent1 extends React.Component<subPropsType1> { ... }
interface subPropsType2 = {
title: string
}
class SubComponent2 extends React.Component<subPropsType2> { ... }
我希望SubComponent1是SuperComponent的唯一有效子项,也就是说,如果我将<SubComponent2 />
或其他类型作为<SuperComponent>
的子项,我希望打字稿可以抛出错误
似乎打字稿仅检查的子项应具有ReactElement的类型,但ts不会检查该子项的道具形状(即subPropsType1),也就是说,如果我将字符串或数字放置为ts将成为SuperComponent的子代,ts会抱怨类型要求不满足,但是如果我在此处放置任何jsx标记(它将被转换为ReactElement),ts会保持沉默
有什么主意吗?如果需要在此处发布任何配置,请随时询问
真的很感谢任何想法和解决方案
答案 0 :(得分:7)
从TypeScript 3.1开始,所有JSX元素都被硬编码为JSX.Element
类型,因此无法接受某些JSX元素,而不能接受其他元素。如果要进行这种检查,则必须放弃JSX语法,定义自己的元素工厂函数,该函数包装React.createElement
,但为不同的组件类型返回不同的元素类型,并手动写入对该工厂函数的调用。
有an open suggestion,它可能在TypeScript 3.2(将于2018年11月下旬发布)之后立即实施,以便TypeScript根据工厂函数的实际返回类型为JSX元素分配类型。给定的组件类型。如果实现了这一点,您将能够定义自己的工厂函数,该工厂函数包装React.createElement
并使用jsxFactory
编译器选项进行指定,您将获得其他类型信息。也许@types/react
甚至会改变,以便React.createElement
提供更丰富的类型信息,如果可以做到的话,不会对不关心功能的项目造成有害影响;我们将不得不拭目以待。
答案 1 :(得分:0)
我可能会声明SuperPropsType.children
为:
children: React.ReactElement<SubPropsType1> | React.ReactElement<SubPropsType1>[];
要考虑有一个孩子和多个孩子的可能性。
在任何情况下,正如已经指出的那样,这将无法按预期进行。
您可以做的是声明一个道具,比方说subComponentProps: SubPropsType1[]
,以传递需要创建这些SubComponent1
(而不是它们的JSX)的道具,并在{{1 }}:
SuperComponent