Typescript: Der JSX-Elementtyp hat in v3.2.0-rc keine Konstrukt- oder Aufrufsignaturen

Erstellt am 21. Nov. 2018  ·  27Kommentare  ·  Quelle: microsoft/TypeScript

TypeScript-Version: 3.2.0-rc, 3.2.1

Code

import * as React from "react";
import { Component, ReactType} from "react";
function App(props:{component:ReactType}) {
  const Comp: ReactType = props.component
  return (<Comp />)
}

Erwartetes Verhalten:
Sollte normal als TypeScript 3.1.6 ausgegeben werden

Tatsächliches Verhalten:
TS2604: JSX element type 'Comp' does not have any construct or call signatures.

Bug JSTSX Duplicate

Hilfreichster Kommentar

Für mich war die Lösung:

export type WrapperProps = {
    mainApp: React.ElementType
}

Alle 27 Kommentare

Hier fehlt der Rest der Fehlermeldung. Stellen Sie jedoch sicher, dass Sie sich auf der neuesten Version von @types/react und dass in Ihren node_modules oder in der Sperrdatei keine Duplikate mehr vorhanden sind.

BEARBEITEN: Sie möchten wahrscheinlich ComponentType und nicht ReactType verwenden

@ Kovensky

Ich habe sichergestellt, dass die neuesten @types/react 16.7.7 und keine Duplikate @types/react in yarn.lock .
Wenn das Problem auf die Duplizierung von @types/react , wird der Fehler Duplication of definition ... .

Ich kehre zu "typescript": "^3.1.6" dann funktioniert es normal.

Typoskript 3.2.1

anderes Beispiel


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 ...

Es sieht so aus, als ob das Problem mit neuen Änderungen an "nullbaren Diskriminanten" zusammenhängt. Es sieht so aus, als ob ts keine gemeinsame Schnittstelle für diese Typen finden kann.
Anderes Beispiel

interface P1 {
  p?: any
  c?: string // remove this and it's ok
}

interface P2 {
  p?: boolean
}

Wir haben ein ähnliches Problem, schnelles Beispiel:

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

Ich sehe dieses Verhalten als völlig ungültig an, da A und B die gleichen Typen haben . Gleichzeitig haben B und D ähnliche Typen_, aber D ist nicht zuweisbar 🤔

Code im Repo: https://github.com/layershifter/ts-issue

Sie tun es nicht, weil Sie const . Die Art von A ist typeof configEmpty.ElementType , aber die Art von B ist 'div' . Die Verwendung von let s zeigt auf beiden das gleiche Verhalten.

@Kovensky was ist mit A und C ? Warum funktioniert C während A mit einem Fehler von does not have any construct fehlschlägt?

Das liegt daran, dass ich den Typ von ReactType verbessert habe, um Komponenten auszuschließen, die die Requisiten, die Sie ihm geben, nicht empfangen können. Da keines der DOM-Elemente { a: string | undefined } empfangen kann, werden sie alle ausgeschlossen, und es dürfen nur noch Funktions- / Klassenkomponenten zugewiesen werden.

@ Kovensky danke 👍 Jetzt ist das Problem mit der Zuordnung für mich klar, aber was ist damit?

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 und B haben dieselben offensichtlich definierten Typen. Warum schlägt A fehl? Es ist wirklich verwirrend.

Ich würde wahrscheinlich sagen, dass der Fehler von @goloveychuk ähnlich dem von # 28795 und # 28768 ist, basierend auf dem bedingten JSX-Konstruktor.

Hm, das Problem ist also, dass ReactType<any> eine Vereinigung von _jedem eingebauten jsx-Tag_ (plus ComponentType<any> , aber dieser Teil ist nicht problematisch) zurückgibt und die Signaturen für diese Komponenten nicht trivial vereinfachen (gibt es keine Unterschrift, die alle anderen perfekt umfasst). Auch dies hängt davon ab, dass # 7294 behoben werden muss. Auf der positiven Seite ist die zugrunde liegende Änderung, die zur Behebung all dieser gemeldeten JSX-Probleme erforderlich ist, dieselbe.

Für den Kontext stellen wir effektiv einen Typ wie diesen her:

declare const JsxSigs: {[K in keyof JSX.IntrinsicElements]: ((props: JSX.IntrinsicElements[K]) => JSX.Element)}[keyof JSX.IntrinsicElements];

was letztendlich zu einer Vereinigung einer Tonne einzigartiger Signaturen führt.

Bevor ich es geändert habe, um eine Vereinigung aller eingebauten jsx-Tags zu sein, war es _just_ string | ComponentType<any> , was noch schlimmer war.

Ja, zumal vor 3.2 ein string -Typ in einem Tag nur leise _disabled_ typechecker eingab, weil der Fehler "Index nicht gefunden", den er ausgeben sollte, nie aufgetreten ist.

Dieses Problem wurde als Duplikat markiert und hat am letzten Tag keine Aktivität gesehen. Es wurde aus Gründen der automatischen Haushaltsführung geschlossen.

Auf ein Problem stoßen, das möglicherweise damit zusammenhängt. Ich habe die folgende Komponente:

function MaybeLabel(props: { useLabel: boolean }) {
   const { useLabel } = props;
   const TagName = useLabel ? 'label' : 'div';

   return <TagName>Woookie</TagName>
}

was in ... endet

error TS2604: JSX element type 'TagName' does nicht have any construct or call signatures.

während

function MaybeLabel2(props: { useLabel: boolean }) {
   const { useLabel } = props;
   const TagName = useLabel ? 'span' : 'div';

   return <TagName>Woookie</TagName>
}

ist für den Typoskript-Compiler völlig akzeptabel. Wie es ist:

export function MaybeLabel3(props: { useLabel: boolean }) {
    const { useLabel } = props;
    const TagName = useLabel ? 'label' : 'div';

    return React.createElement(TagName, 'Wookie')
}

Der einzige Unterschied bei MaybeLabel2 besteht darin, dass ich span anstelle von label (die Verwendung von span anstelle von div scheint ebenfalls akzeptabel zu sein ). MaybeLabel3 macht es noch seltsamer, da dies genau das sein sollte, was MaybeLabel kompiliert.

Verwenden Sie die neueste Version von @ types / react und @ types / react-dom und überprüfen Sie das Problem in Typoskript 3.2.1, 3.2.2 und 3.3.0-dev.20181219. In 3.1.6 funktioniert alles wie erwartet (keines der Beispiele führt zu Fehlern)

Für mich war die Lösung:

export type WrapperProps = {
    mainApp: React.ElementType
}

@ TacB0sS bitte

Ich habe den Thread möglicherweise falsch verstanden, wollte aber einen Verweis auf ein jsx-Element an ein anderes jsx-Element übergeben:

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>)
});

Zusammen mit:

export type WrapperProps = {
    mainApp: React.ElementType<{prop1:string}>
}

@ TacB0sS Für mich war der Haupttrick das Hinzufügen der Bedingung if . Sieht so aus, als wäre es egal, ob Sie React.ComponentType oder React.ElementType

Ich bin mir nicht sicher, ob ich das Ergebnis verstehe. Ich habe einen ähnlichen Fehler, den ich nicht beheben konnte. Hier ist mein Anwendungsfall:

// 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 }}
    />
  );
};

und dann benutze ich es so in einer anderen Komponente wie folgt:

const Header: React.SFC<{}> = () => {
  return (
    <div>
      <Logo tag="h1" aria-label="Syn By Design: Eric Masiello's Portfolio" />
      Header online
    </div>
  );
};

Wenn ich den Compiler starte, erhalte ich folgende Fehlermeldung:

components/Logo.tsx:13:6 - error TS2604: JSX element type 'Tag' does not have any construct or call signatures.

13     <Tag
        ~~~


Found 1 error.

Irgendwelche Ideen, wie das funktioniert?

Verwenden Sie anstelle von Component ComponentClass

Ich habe diesen Fehler erhalten, weil ich Standard importiert habe, aber den entsprechenden Export in der Datei .d.ts als benannt anstelle von Standard deklariert habe ... hat mich eine Weile verwirrt

Ich wollte das nur hier hinzufügen. Sie sind sich nicht sicher, ob dies bereits gesagt wurde, aber wenn Sie eine Mietauftragskomponente ausführen, möchten Sie den Typ React.ComponentType verwenden

. " https://flow.org/en/docs/react/types/#toc -react-componenttype"

@ericmasiello Am Ende React.ElementType für eine dynamisch übergebene Komponente verwendet. Mein Anwendungsfall ist im Grunde der folgende:

type Props = {
    heading: React.ElementType
}
const Header: FC<Props> = props => {
    const Header = props.heading ?? 'h2';
    return (
        <Header className="some-class"><children /></Header>
    )
}

@ericmasiello Am Ende React.ElementType für eine dynamisch übergebene Komponente verwendet. Mein Anwendungsfall ist im Grunde der folgende:


type Props = {

    heading: React.ElementType

}

const Header: FC<Props> = props => {

    const Header = props.heading ?? 'h2';

    return (

        <Header className="some-class"><children /></Header>

    )

}

Cool! Welche Version von Typescript und welche Version von @ types / react haben Sie installiert?

@ericmasiello

Cool! Welche Version von Typescript und welche Version von @ types / react haben Sie installiert?

[email protected]
@ types / [email protected]

Ich habe dieses Problem gelöst, indem ich eines dieser beiden Dinge getan habe:

Fall 1:

.d.ts Datei:

declare module "foo" {
   interface PropFoo {
      propy: string;
   }

   class MyTypedComponent extends React.Component<PropFoo> { }
}

Reagieren:

import MyTypedComponent from "foo";

function AnotherComponent() {

   /* Notice in here we have to use the dot operator and reference the component */
   return <MyTypedComponent.MyTypedComponent /> 
}

Beachten Sie, dass wir _MyTypedComponent.MyTypedComponent_ schreiben müssen, um die neu typisierte Komponente zu verwenden. Dies mag für einige Leute offensichtlich sein, aber ich habe viel Zeit verschwendet, als ich beim Importieren und Verweisen auf die Komponente nur den Punktoperator verwenden musste.

Fall 2 [nur eine andere Art, Fall 1 zu schreiben]:

.d.ts Datei:

declare module "foo" {
   interface PropFoo {
      propy: string;
   }

   export default class MyTypedComponent extends React.Component<PropFoo> { } //Notice the export default in here
}

Reagieren:

import MyTypedComponent from "foo";

function AnotherComponent() {

   /* Since this component is default exported, no need to use the dot operator */
   return <MyTypedComponent /> 
}

Überprüfen Sie also im Grunde Ihre Exporte, Standardexporte und Importe und stellen Sie sicher, dass Sie richtig referenzieren.

Mein Englisch tut mir sehr leid und ich hoffe, das hilft.

Für mich war die Lösung:

export type WrapperProps = {
  mainApp: React.ElementType
}

niu b

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

Antony-Jones picture Antony-Jones  ·  3Kommentare

jbondc picture jbondc  ·  3Kommentare

kyasbal-1994 picture kyasbal-1994  ·  3Kommentare

dlaberge picture dlaberge  ·  3Kommentare

seanzer picture seanzer  ·  3Kommentare