Typescript: El tipo de elemento JSX no tiene ninguna construcción o signaturas de llamada en v3.2.0-rc

Creado en 21 nov. 2018  ·  27Comentarios  ·  Fuente: microsoft/TypeScript

Versión de TypeScript: 3.2.0-rc, 3.2.1

Código

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

Comportamiento esperado:
Debería generar una salida normal como TypeScript 3.1.6

Comportamiento real:
TS2604: JSX element type 'Comp' does not have any construct or call signatures.

Bug JSTSX Duplicate

Comentario más útil

para mi la solución fue:

export type WrapperProps = {
    mainApp: React.ElementType
}

Todos 27 comentarios

A esto le falta el resto del mensaje de error pero, para estar seguro, asegúrese de estar en la última versión de @types/react y de que no queden duplicados en su node_modules o archivo de bloqueo.

EDITAR: probablemente quiera usar ComponentType y no ReactType

@Kovensky

Me he asegurado de usar el último @types/react 16.7.7 y no duplicados @types/react en yarn.lock .
Si el problema se debe a la duplicación de @types/react , devolverá el error Duplication of definition ... .

Vuelvo a "typescript": "^3.1.6" luego funciona normalmente.

Texto mecanografiado 3.2.1

otro ejemplo


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

Parece que el problema está relacionado con nuevos cambios de "discriminantes que aceptan valores NULL". Parece que ts no puede encontrar una interfaz común para esos tipos.
Otro ejemplo

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

interface P2 {
  p?: boolean
}

Tenemos un problema similar, ejemplo rápido:

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

Veo este comportamiento como completamente inválido, porque A y B tienen los mismos tipos . Al mismo tiempo, B y D tienen _ tipos similares_, pero D no se pueden asignar 🤔

Código en repositorio: https://github.com/layershifter/ts-issue

No lo hacen, porque estás usando const . El tipo de A es typeof configEmpty.ElementType , pero el tipo de B es 'div' . El uso de let s mostrará el mismo comportamiento en ambos.

@Kovensky ¿qué pasa con A y C ? ¿Por qué C funciona mientras que A falla con el error does not have any construct ?

Eso es porque mejoré el tipo de ReactType para excluir componentes que no podrían recibir los accesorios que le está dando. Debido a que ninguno de los elementos DOM puede recibir { a: string | undefined } , todos están excluidos y solo se les permite asignarle componentes de función / clase.

@Kovensky gracias 👍 Ahora el problema con la asignación está claro para mí, pero ¿qué pasa con esto?

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 y B tienen los mismos tipos definidos obviamente, ¿por qué A falla? Es algo realmente confuso.

Probablemente diría que el error de @rexpan y @goloveychuk es similar al # 28795 y # 28768 basado en el constructor JSX condicional.

Hm, entonces el problema es que ReactType<any> devuelve una unión de _ cada etiqueta jsx incorporada_ (más ComponentType<any> , pero esa parte no es problemática), y las firmas para esos componentes no se simplifican trivialmente (hay no una firma que englobe perfectamente a todas las demás). Esto también depende de que el # 7294 sea corregido. En el lado positivo, el cambio subyacente necesario para solucionar todos estos problemas JSX que se informan es el mismo.

Para el contexto, fabricamos efectivamente un tipo como este:

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

que termina siendo la unión de un montón de firmas únicas.

Antes de cambiarlo para que fuera una unión de todas las etiquetas jsx integradas, era _just_ string | ComponentType<any> , que era aún peor.

Sí, especialmente desde antes de 3.2, un tipo string en una etiqueta simplemente _disabled_ typechecker silenciosamente, porque el error "índice no encontrado" que se suponía que debía emitir nunca ocurrió.

Este problema se ha marcado como duplicado y no ha tenido actividad en el último día. Se ha cerrado por motivos de mantenimiento automático.

Se encuentra con un problema que podría estar relacionado. Tengo el siguiente componente:

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

   return <TagName>Woookie</TagName>
}

lo que resulta en

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

mientras

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

   return <TagName>Woookie</TagName>
}

es completamente aceptable para el compilador de mecanografiado. Como es:

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

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

Donde la única diferencia en MaybeLabel2 es que estoy usando span lugar de label (usar span lugar de div también parece aceptable ). MaybeLabel3 hace aún más extraño, ya que debería ser exactamente en lo que se compila MaybeLabel .

Usando la última versión de @ types / react y @ types / react-dom, y verifiqué el problema en mecanografiado 3.2.1, 3.2.2 y 3.3.0-dev.20181219. En 3.1.6 todo funciona como se esperaba (ninguno de los ejemplos produce errores)

para mi la solución fue:

export type WrapperProps = {
    mainApp: React.ElementType
}

@ TacB0sS por favor explique.

Es posible que haya entendido mal el hilo, pero quería pasar una referencia a un elemento jsx a otro elemento 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>)
});

Juntos con:

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

@ TacB0sS Para mí, el truco principal fue agregar la condición if . Parece que no importa si usa React.ComponentType o React.ElementType

No estoy seguro de entender el resultado de esto. Tengo un error similar que no he podido resolver. Aquí está mi caso de uso:

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

y luego lo estoy usando así en otro componente así:

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

Cuando ejecuto el compilador, aparece este error:

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

13     <Tag
        ~~~


Found 1 error.

¿Alguna idea de cómo hacer que esto funcione?

En lugar de Component , use ComponentClass

Recibí este error porque importé el valor predeterminado pero declaré la exportación correspondiente como nombrada en lugar de predeterminada en el archivo .d.ts ... me confundió por un tiempo

Solo quería agregar esto aquí. No estoy seguro de si esto ya se dijo, pero si está haciendo un componente de pedido de arrendatario, desea usar el tipo React.ComponentType

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

@ericmasiello Terminé usando React.ElementType para un componente pasado dinámicamente. Mi caso de uso es básicamente el siguiente:

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

@ericmasiello Terminé usando React.ElementType para un componente pasado dinámicamente. Mi caso de uso es básicamente el siguiente:


type Props = {

    heading: React.ElementType

}

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

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

    return (

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

    )

}

¡Frio! ¿Qué versión de TypeScript y qué versión de @ types / react tienes instaladas?

@ericmasiello

¡Frio! ¿Qué versión de TypeScript y qué versión de @ types / react tienes instaladas?

[email protected]
@ tipos / [email protected]

Resolví este problema haciendo cualquiera de estas dos cosas:

Caso 1:

Archivo .d.ts:

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

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

Reaccionar:

import MyTypedComponent from "foo";

function AnotherComponent() {

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

Observe que, para usar el componente recién escrito, tenemos que escribir _MyTypedComponent.MyTypedComponent_. Esto puede ser obvio para algunas personas, pero perdí mucho tiempo cuando todo lo que tenía que hacer era usar el operador de punto en la importación y hacer referencia al componente.

Caso 2 [solo otra forma de escribir el Caso 1]:

Archivo .d.ts:

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

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

Reaccionar:

import MyTypedComponent from "foo";

function AnotherComponent() {

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

Entonces, básicamente, verifique sus exportaciones, exportaciones predeterminadas e importaciones y asegúrese de hacer referencia correctamente.

Lo siento mucho por mi inglés y espero que esto ayude.

para mi la solución fue:

export type WrapperProps = {
  mainApp: React.ElementType
}

niu b

¿Fue útil esta página
0 / 5 - 0 calificaciones