在React中使用Typescript 3.5 +

时间:2019-07-19 20:41:31

标签: reactjs typescript

我有一种情况,我想将 React.FC 的子组件显式地划分为特定类型,并覆盖默认值: React.ReactNode >。

目的是我正在创建一个小库,并且希望出现编译时错误,该错误将告诉用户他只能将特定的组件类型用作父级的子级。

一个 OK 示例如下:

<MainComponent>
    <ChildComponent>
</MainComponent>

失败示例为:

<MainComponent>
    <Route ...>
    <ChildComponent>
</MainComponent>
  • 这应该失败,因为Route组件不是ChildComponent,并且检查失败。

React.FC中的默认子级属性派生自:

interface FunctionComponent<P = {}> {
    (props: PropsWithChildren<P>, context?: any): ReactElement | null;
    propTypes?: WeakValidationMap<P>;
    contextTypes?: ValidationMap<any>;
    defaultProps?: Partial<P>;
    displayName?: string;
}

type PropsWithChildren<P> = P & { children?: ReactNode };

我尝试过的是这样的:

Omit<React.FC, 'children'> & {
  children: ChildComponent | ChildComponent[];
}

但是我只能得到React.ReactNode或我的孩子和React.ReactNode的联合。

似乎无法弄清楚如何覆盖此道具,以便仅将我的类型明确用于此道具。

我正在使用Typescript 3.5.3和Omit / Extend ...,现在已成为标准TS库的一部分。

1 个答案:

答案 0 :(得分:5)

不可能,这不可能。

<MainComponent>
    <ChildComponent/>
</MainComponent>

是JSX语法,将被编译为

React.createElement(MainComponent, null, React.createElement(ChildComponent, null));

然后我们要看一下打字稿如何处理这些JSX元素。这在他们的手册中有明确记录:

  

The JSX result type

     

默认情况下,JSX表达式的结果键入为any。您可以通过指定JSX.Element接口来自定义类型。但是,无法从此接口检索有关JSX的元素,属性或子级的类型信息。这是一个黑匣子。

您可以将children改写为stringfunction(以实现诸如渲染道具模式之类的东西),但是任何自定义组件都将强制转换为JSX.Element是文档中所述的黑匣子。

目前有一个issue可供使用,其中列出了如何概括JSX.Element以支持您的用例的路线图,但是没有明确的时间表,何时何地以及何时登陆