我试图利用最近增加的对TypeScript编译器和@类型/反应中键入儿童的支持,但很挣扎。我使用的是TypeScript版本2.3.4。
假设我有这样的代码:
interface TabbedViewProps {children?: Tab[]}
export class TabbedView extends React.Component<TabbedViewProps, undefined> {
render(): JSX.Element {
return <div>TabbedView</div>;
}
}
interface TabProps {name: string}
export class Tab extends React.Component<TabProps, undefined> {
render(): JSX.Element {
return <div>Tab</div>
}
}
当我尝试这样使用这些组件时:
return <TabbedView>
<Tab name="Creatures">
<div>Creatures!</div>
</Tab>
<Tab name="Combat">
<div>Combat!</div>
</Tab>
</TabbedView>;
我得到一个错误如下:
ERROR in ./src/typescript/PlayerView.tsx
(27,12): error TS2322: Type '{ children: Element[]; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<TabbedView> & Readonly<{ children?: ReactNode; }> ...'.
Type '{ children: Element[]; }' is not assignable to type 'Readonly<TabbedViewProps>'.
Types of property 'children' are incompatible.
Type 'Element[]' is not assignable to type 'Tab[] | undefined'.
Type 'Element[]' is not assignable to type 'Tab[]'.
Type 'Element' is not assignable to type 'Tab'.
Property 'render' is missing in type 'Element'.
它似乎只是将子类型推断为Element[]
而不是Tab[]
,尽管这是我使用的唯一类型的子类型。
编辑:也可以限制子道具的接口,而不是直接限制子组件的类型,因为我所需要做的就是从子组件中提取一些特定的道具。
编辑2:结果表明这种方法阻止了警告,但是根据注释TabProps
没有正确检查。
您应该尝试这样设置界面选项卡ViewProps的子级
interface TabbedViewProps { children?: React.ReactElement<TabProps>[] }
这里的想法不是告诉你的TabbedView
有一个Tab
数组,而是告诉你的TabbedView
有一个需要特定道具的元素
数组。在您的情况下TabProps
。
编辑(thx到Matei):
interface TabbedViewProps {
children?: React.ReactElement<TabProps>[] | React.ReactElement<TabProps>
}
作为指针,声明TabbedView.children
为:
children: React.ReactElement<TabProps> | React.ReactElement<TabProps>[];
将摆脱错误,但它不会正确地检查子项。也就是说,您仍然可以将TabProps
以外的子级传递到TabbedView
而不会出现任何错误,因此这也是有效的:
return (
<TabbedView>
<Tab name="Creatures">
<div>Creatures!</div>
</Tab>
<Tab name="Combat">
<div>Combat!</div>
</Tab>
<NotTabButValidToo />
</TabbedView>
);
你可以做的是声明一个道具,比方说选项卡: TabProps[]
,来传递你需要的道具来创建那些选项卡
,而不是他们的JSX,并在选项卡视图
中呈现它们:
interface TabbedViewProps {
children?: never;
tabs?: TabProps[];
}
...
const TabbedView: React.FC<TabbedViewProps > = ({ tabs }) => {
return (
...
{ tabs.map(tab => <Tab key={ ... } { ...tab } />) }
...
);
};
我试图断言类型。你可以扔,也可以忽略。
interface TabbedViewProps {
children?: React.ReactElement<ITabProps> | React.ReactElement<ITabProps>[]
}
在组件本身中,映射子级并断言或忽略
{React.Children.map(props.children, (tab) => {
if(tab?.type != Tab) return;
console.log(tab?.type == Tab);
return tab;
})}