从字符串创建JSX元素的正确TypeScript类型

时间:2019-06-19 20:50:35

标签: javascript reactjs typescript

我有一个想要默认呈现为{ "@odata.context": "https://filesearch.search.windows.net/indexes('index-path2')/$metadata#docs(*)", "value": [ { "@search.score": 1, "metadata_storage_name": "RmljaGFfMTAwQ29kY2xpNTY0ODg1NDNGLmpzb241", "metadata_storage_path": "https://pruebaqueriesstorage.blob.core.windows.net/contenedorblob/Ficha_100Codcli56488543F.json" }, { "@search.score": 1, "metadata_storage_name": "RmljaGFfMTBDb2RjbGk5MDQxODAxMkQuanNvbg2", "metadata_storage_path": "https://pruebaqueriesstorage.blob.core.windows.net/contenedorblob/Ficha_10Codcli90418012D.json" }, { "@search.score": 1, "metadata_storage_name": "RmljaGFfMTFDb2RjbGkzMTYzNTU0N0UuanNvbg2", "metadata_storage_path": "https://pruebaqueriesstorage.blob.core.windows.net/contenedorblob/Ficha_11Codcli31635547E.json" }, 的组件。我希望消费者能够根据需要指定其他元素。下面的代码导致错误:

h2

我想我理解为什么会失败,TS希望呈现一个React节点。为了清楚起见,只要变量以大写字母开头(这是JSX的要求),React 都可以将引用的元素呈现为字符串。我在香草JS + React上成功完成此操作之前,我只是不知道如何满足TypeScript。

如何获取TypeScript而不使用TS2604 - JSX element type 'ElementType' does not have any construct or call signatures

来呈现此内容
elementType?: any

5 个答案:

答案 0 :(得分:2)

使用keyof JSX.IntrinsicElements

import * as React from 'react'

interface Props {
  children: React.ReactNode;
  elementType?: keyof JSX.IntrinsicElements;
}

export default function ({ children, elementType: ElementType = 'h2' }: Props): JSX.Element {
  return (
    <ElementType>{children}</ElementType>
  );
}

答案 1 :(得分:1)

首先,介绍一下JSX。它只是JavaScript表达式React.createElement的语法糖。

基于这些知识,现在让我们看一下TypeScript抱怨的原因。您将elementType定义为string,但是,当您实际使用它时,它将成为JavaScript表达式。 string类型的课程没有任何构造或呼叫签名。

现在我们知道了根本原因。在React中,有一个名为FunctionComponent的类型。如您所料,它是一个函数表达式,这正是我们想要的。因此,您可以将elementType定义为string | FunctionComponent。这应该使TypeScript开心:)

仅供参考:定义道具类型的推荐方法是:

const MyComponent: FunctionComponent<Props> = (props) => {}

答案 2 :(得分:0)

鉴于组件定义如下,对我有用:

interface LabelProps {
        ...
        tag?: React.ElementType | string;
    }

const Label: VFC<LabelProps> = ({
       ...other props...
        tag: Element = 'span',
    }) => (
        <Element>
            {children}
        </Element>
    );

和道具类型:

Label.propTypes = {
    ...
    tag: PropTypes.oneOfType([PropTypes.elementType, PropTypes.string]),
};

答案 3 :(得分:0)

如果你只想要任何 jsx元素的类型,你可以使用

type jsxType = JSX.IntrinsicElements[keyof JSX.IntrinsicElements]

这将接受任何 jsx 元素。

答案 4 :(得分:-1)

那是行不通的,您需要使用React.createElement()。 https://reactjs.org/docs/react-api.html#createelement

类似这样

  import React, {ReactNode} from 'react'

interface Props {
    children: ReactNode,
    elementType?: string,
}

export default function ({children, elementType: ElementType = 'h2'}: Props): JSX.Element {

    return React.createElement(elementType, {}, children); 
}