假设您有以下组件,该组件接受一个或多个子JSX.Elements,并在使用React.cloneElement(child, { onCancel: () => {} }
呈现它们时将额外的回调传递给它们的props。
相关组件(摘录):
interface XComponentProps {
onCancel: (index: number) => void;
}
class XComponent extends React.Component<XComponentProps> {
render() {
const { onCancel } = this.props;
const children = typeof this.props.children === 'function' ?
React.cloneElement(this.props.children, { onCancel: () => onCancel() }) :
this.props.children.map((child, idx) => (
React.cloneElement(child, { onCancel: () => onCancel(idx) })
));
return <div>{children}</div>;
}
}
正在使用的相关组件(摘录):
interface UserComponentProps { caption: string }
const UserComponent = (props: UserComponentProps) => (
<button onClick={props.onClose}>{props.caption || "close"}</button>
);
ReactDOM.render(
<XComponent onCancel={handleCancel}>
<UserComponent />
<UserComponent />
<UserComponent />
</XComponent>
);
现在TSC抱怨UserComponent
在其props的接口定义中没有onCancel
,实际上没有。一个最简单的解决方法是手动将onCancel
定义为UserComponentProps
接口。
但是,我想在不修改子节点的prop定义的情况下修复它,这样组件就可以接受任意的React元素集。在这种情况下,是否有办法定义返回元素的类型,这些元素在XComponent
(父节点)级别传递额外的隐式prop?
6条答案
按热度按时间a6b3iqyw1#
这是不可能的。没有办法静态地知道UserComponent从ReactDOM.render上下文中的父XComponent接收到什么属性。
如果需要类型安全的解决方案,请使用子级作为函数:
以下是
XComponent
的定义现在您可以使用它来渲染
UserComponent
我经常使用这种模式,这会很好地工作。您可以重构XComponentProps,以键入带有相关部分的
childrenAsFunction
属性(此处为onCancel
函数)。yptwkmov2#
您可以使用接口继承(参见Extending Interfaces)并让UserComponentProps扩展XComponentProps:
interface UserComponentProps extends XComponentProps { caption: string }
这将给予UserComponentProps提供XComponentProps的所有属性以及它自己的属性。
如果你不想让UserComponentProps定义XComponentProps的所有属性,你也可以使用Partial类型(参见Mapped Types):
interface UserComponentProps extends Partial<XComponentProps> { caption: string }
这将给予UserComponentProps提供XComponentProps的所有属性,但使它们成为可选属性。
dvtswwa33#
你可以把child作为一个函数来传递,即使在JSX中也是如此。这样你就可以得到正确的输入。UserComponents props接口应该扩展ChildProps。
qcbq4gxm4#
正如@Benoit B.所说:
这是不可能的。没有办法静态地知道UserComponent从ReactDOM.render上下文中的父XComponent接收到什么属性。
也就是说,有一种替代方法可以实现这一点,即使用高阶分量来 Package
UserComponent
(不修改它,如果有意义,可以重命名):您还可以将
Omit & Pick
简化为MakeOptional
类型帮助器:edqdpe6u5#
我知道这个问题已经解决了,但是另一个解决方案是限制可以传递的子元素的类型。限制 Package 器的功能,但是可能是您想要的。
所以如果你保留原来的例子:
4zcjmb1e6#
更新:解决方案2021
遇到此问题后,我找到了一个巧妙的解决方法:
将使用标签组件作为一个例子,但它是相同的问题正在解决(即保持TS高兴时,动态添加 prop 到子组件,从父组件)。
一个月一次
一米一分一秒
App.tsx