TypeScript版本: 3.2.0-rc,3.2.1
码
import * as React from "react";
import { Component, ReactType} from "react";
function App(props:{component:ReactType}) {
const Comp: ReactType = props.component
return (<Comp />)
}
预期行为:
应该输出正常的TypeScript 3.1.6
实际行为:
TS2604: JSX element type 'Comp' does not have any construct or call signatures.
这遗漏了错误消息的其余部分,但是可以肯定的是,请确保您使用的是最新版本的@types/react
并且在node_modules或lock文件中没有重复的消息。
编辑:您可能打算使用ComponentType而不是ReactType
@科文斯基
我确保使用最新的@types/react 16.7.7
并且在yarn.lock
没有重复的@types/react
yarn.lock
。
如果问题是由于重复@types/react
,它将返回错误Duplication of definition ...
。
我恢复为"typescript": "^3.1.6"
然后它可以正常工作。
打字稿3.2.1
其他例子
interface P1 {
p?: boolean
c?: string
}
interface P2 {
p?: boolean
c?: any // if you replace c with string, error goes away
d?: any
}
declare var C: React.ComponentType<P1> | React.ComponentType<P2>
const a = <C p={true} /> // element does not have any ...
看起来,问题与新的“可为空的判别式”更改有关。 看起来ts找不到这些类型的通用接口。
其他例子
interface P1 {
p?: any
c?: string // remove this and it's ok
}
interface P2 {
p?: boolean
}
我们有一个类似的问题,简单的例子:
import * as React from 'react'
//
// Types
//
interface Config<P> {
ElementType: React.ReactType<P>
}
interface EmptyProps {
}
interface Props {
a?: string
}
type HProps = {
configEmpty: Config<EmptyProps>,
config: Config<Props>
}
//
// Component
//
const H: React.FC<HProps> = ({ config, configEmpty }) => {
const A: React.ReactType<EmptyProps> = configEmpty.ElementType // assigned
const B: React.ReactType<EmptyProps> = 'div' // assigned
const C: React.ReactType<Props> = config.ElementType // assigned
const D: React.ReactType<Props> = 'div' // in this case assignment failed
return (
<div>
<A/> {/* TS2604: JSX element type 'A' does not have any construct or call signatures. */}
<B/>
<C/>
<D/>
</div>
)
}
export default H
我认为此行为完全无效,因为A
和B
具有相同的类型。 同时, B
和D
具有相似的类型_,但是D
无法分配🤔
回购代码: https :
他们没有,因为您使用的是const
。 A
为typeof configEmpty.ElementType
,但是B
为'div'
。 使用let
s将在两者上显示相同的行为。
@Kovensky A
和C
呢? 为什么C
可以工作,而A
失败并出现does not have any construct
错误?
那是因为我改进了ReactType
的类型,以排除将无法接收您提供的道具的组件。 因为没有一个DOM元素可以接收{ a: string | undefined }
,所以它们都被排除在外,并且仅允许将功能/类组件分配给它。
@Kovensky谢谢👍现在我很清楚分配的问题,但是那又如何呢?
import * as React from 'react'
//
// Types
//
interface Config<P> {
ElementType: React.ReactType<P>
}
interface Empty {}
interface Props { a?: string }
type HProps = {
configEmpty: Config<Empty>,
config: Config<Props>
}
//
// Component
//
const H: React.FC<HProps> = ({ config, configEmpty }) => {
const A: React.ReactType<Empty> = configEmpty.ElementType // is React.ReactType<Empty>
const B: React.ReactType<Empty> = 'div' // is string
const C: React.ReactType<Props> = config.ElementType // is React.ReactType<Props>
return (
<div>
{/* React.ReactType<Empty> */} <A/> {/* <--- TS2604: JSX element type 'A' does not have any construct or call signatures. */}
{/* React.ReactType<Empty> */} <B/>
{/* React.ReactType<Props> */} <C/>
</div>
)
}
export default H
A
和B
具有相同的明显定义的类型,为什么A
失败? 这真是令人困惑。
我可能会说@rexpan和@goloveychuk的错误类似于基于条件JSX构造函数的#28795和#28768。
嗯,所以问题在于ReactType<any>
返回一个_every内置jsx tag_的联合(加上ComponentType<any>
,但是那部分没有问题),并且这些组件的签名并没有简单化(存在不能完美地涵盖所有其他签名)。 这也依赖于#7294进行修复。 从好的方面来说,解决所有已报告的JSX问题所需的基础更改是相同的。
对于上下文,我们有效地制造了这样的类型:
declare const JsxSigs: {[K in keyof JSX.IntrinsicElements]: ((props: JSX.IntrinsicElements[K]) => JSX.Element)}[keyof JSX.IntrinsicElements];
最终是大量独特签名的结合。
在我将其更改为所有内置jsx标签的并集之前,它是_just_ string | ComponentType<any>
,甚至更糟。
是的,特别是从3.2之前的版本开始,在标记中的string
类型只是悄悄地禁用了typechecker,因为它应该发出的“找不到索引”错误从未发生过。
该问题已被标记为重复,并且在最后一天没有任何活动。 出于自动整理房间的目的已关闭。
遇到可能相关的问题。 我有以下组成部分:
function MaybeLabel(props: { useLabel: boolean }) {
const { useLabel } = props;
const TagName = useLabel ? 'label' : 'div';
return <TagName>Woookie</TagName>
}
导致
error TS2604: JSX element type 'TagName' does
不是have any construct or call signatures.
而
function MaybeLabel2(props: { useLabel: boolean }) {
const { useLabel } = props;
const TagName = useLabel ? 'span' : 'div';
return <TagName>Woookie</TagName>
}
是打字稿编译器完全可以接受的。 照原样:
export function MaybeLabel3(props: { useLabel: boolean }) {
const { useLabel } = props;
const TagName = useLabel ? 'label' : 'div';
return React.createElement(TagName, 'Wookie')
}
其中MaybeLabel2
的唯一区别是我使用span
而不是label
(使用span
而不是div
似乎也可以接受) )。 MaybeLabel3
使其变得更加陌生,因为那应该正是MaybeLabel
编译的内容。
使用最新版本的@ types / react和@ types / react-dom,并验证了打字稿3.2.1、3.2.2和3.3.0-dev.20181219中的问题。 在3.1.6中,所有操作均按预期进行(所有示例均未产生错误)
对我来说解决方案是:
export type WrapperProps = {
mainApp: React.ElementType
}
@ TacB0sS请详细说明。
我可能对线程有误解,但我想将对jsx元素的引用传递给另一个jsx元素:
export const AppWrapper = hot(module)((props: WrapperProps) => {
const MainApp = props.mainApp;
if (!MainApp) // <-- JSX elements MUST start with upper case!!
throw new ImplementationMissingException("mainApp was not specified!!");
return (
<Router history={BrowserHistoryModule.getHistory()}>
<MainApp prop1={"value"}/>
</Router>)
});
和...一起:
export type WrapperProps = {
mainApp: React.ElementType<{prop1:string}>
}
@ TacB0sS对我来说,主要技巧是添加if
条件。 看起来无论使用React.ComponentType
还是React.ElementType
我不确定我是否了解这一结果。 我有一个类似的错误,我无法解决。 这是我的用例:
// Logo.tsx
import classNames from 'classnames';
interface Props extends React.HTMLAttributes<HTMLElement> {
tag?: React.ReactType;
}
const Logo: React.SFC<Props> = props => {
const { tag: Tag = 'div', className, ...rest } = props;
return (
<Tag
className={classNames(styles.logo, className)}
{...rest}
dangerouslySetInnerHTML={{ __html: logo }}
/>
);
};
然后我在另一个组件中像这样使用它:
const Header: React.SFC<{}> = () => {
return (
<div>
<Logo tag="h1" aria-label="Syn By Design: Eric Masiello's Portfolio" />
Header online
</div>
);
};
当我运行编译器时,出现此错误:
components/Logo.tsx:13:6 - error TS2604: JSX element type 'Tag' does not have any construct or call signatures.
13 <Tag
~~~
Found 1 error.
任何想法如何使这项工作?
代替Component
,使用ComponentClass
我收到此错误的原因是我导入了默认值,但在.d.ts
文件中声明了相应的导出名称,而不是默认值。
只是想在这里添加。 不知道这是否已经说过,但是如果您正在做一个租赁订单组件,则要使用React.ComponentType类型
。 “ https://flow.org/en/docs/react/types/#toc -react-componenttype”
@ericmasiello我最终使用React.ElementType
作为动态传递的组件。 我的用例基本上如下:
type Props = {
heading: React.ElementType
}
const Header: FC<Props> = props => {
const Header = props.heading ?? 'h2';
return (
<Header className="some-class"><children /></Header>
)
}
@ericmasiello我最终使用
React.ElementType
作为动态传递的组件。 我的用例基本上如下:type Props = { heading: React.ElementType } const Header: FC<Props> = props => { const Header = props.heading ?? 'h2'; return ( <Header className="some-class"><children /></Header> ) }
凉! 您安装了哪个版本的Typescript和哪个版本的@ types / react?
@ericmasiello
凉! 您安装了哪个版本的Typescript和哪个版本的@ types / react?
[email protected]
@ types / [email protected]
通过执行以下两项操作,我解决了这个问题:
.d.ts文件:
declare module "foo" {
interface PropFoo {
propy: string;
}
class MyTypedComponent extends React.Component<PropFoo> { }
}
反应:
import MyTypedComponent from "foo";
function AnotherComponent() {
/* Notice in here we have to use the dot operator and reference the component */
return <MyTypedComponent.MyTypedComponent />
}
注意,为了使用新类型的组件,我们必须编写_MyTypedComponent.MyTypedComponent_。 这对于某些人可能是显而易见的,但是当我要做的就是在导入中使用点运算符并引用该组件时,我浪费了很多时间。
.d.ts文件:
declare module "foo" {
interface PropFoo {
propy: string;
}
export default class MyTypedComponent extends React.Component<PropFoo> { } //Notice the export default in here
}
反应:
import MyTypedComponent from "foo";
function AnotherComponent() {
/* Since this component is default exported, no need to use the dot operator */
return <MyTypedComponent />
}
因此,基本上,请检查您的导出,默认导出和导入,并确保引用正确。
非常抱歉我的英语水平,希望对您有所帮助。
对我来说解决方案是:
export type WrapperProps = { mainApp: React.ElementType }
牛
最有用的评论
对我来说解决方案是: