Búsqueda de sitios web

Usando componentes web dentro de Preact y TypeScript


Estoy usando custom-elements o componentes web dentro de Preact. El problema es que Typescript se queja de que los elementos no están definidos en JSX.IntrinsicElements - en este caso un elemento check-box:

<div className={styles.option}>
    <check-box checked={this.prefersDarkTheme} ref={this.svgOptions.darkTheme}/>
    <p>Dark theme</p>
</div>

Mensaje de error (ruta omitida):

ERROR in MyComponent.tsx
[tsl] ERROR in MyComponent.tsx(50,29)
      TS2339: Property 'check-box' does not exist on type 'JSX.IntrinsicElements'.

Me encontré con las siguientes posibles soluciones, que desafortunadamente no funcionan:

  1. https://stackoverflow.com/a/57449556/7664765 - Es una respuesta que no está realmente relacionada con la pregunta, pero cubrió mi problema

He intentado agregar lo siguiente a mi archivo typings.d.ts:

import * as Preact from 'preact';

declare global {
    namespace JSX {
        interface IntrinsicElements {
            'check-box': any; // The 'any' just for testing purposes
        }
    }
}

Mi IDE atenuó la parte de importación y IntrinsicElements lo que significa que no se usa (?!) y de todos modos no funcionó. Todavía estoy recibiendo el mismo mensaje de error.

  1. https://stackoverflow.com/a/55424778/7664765 - También para React, he intentado "convertir" a Preact y obtuve los mismos resultados que para 1.

Incluso he encontrado un archivo mantenido por Google en el proyecto Squoosh donde hicieron lo siguiente para "polyfill" el soporte:

En la misma carpeta que el componente, un archivo missing-types.d.ts con el siguiente contenido, básicamente la misma configuración que tengo pero con un archivo index.ts en lugar de check-bock.ts y están usando una versión anterior de TS v3.5.3:

declare namespace JSX {
  interface IntrinsicElements {
    'range-input': HTMLAttributes;
  }
}

Supongo que su compilación no falló, así que ¿cómo funciona y cómo defino correctamente los elementos personalizados para usarlos dentro de componentes de preact/react?

Actualmente estoy usando [email  y [email .

Respuesta #1

Está bien, logré resolverlo usando la ampliación de módulos:

declare module 'preact/src/jsx' {
    namespace JSXInternal {

        // We're extending the IntrinsicElements interface which holds a kv-list of
        // available html-tags.
        interface IntrinsicElements {
            'check-box': unknown;
        }
    }
}

Usando la interfaz HTMLAttributes podemos indicar a JSX qué atributos están disponibles para nuestro elemento personalizado:

// Your .ts file, e.g. index.ts
declare module 'preact/src/jsx' {
    namespace JSXInternal {
        import HTMLAttributes = JSXInternal.HTMLAttributes;

        interface IntrinsicElements {
            'check-box': HTMLAttributes<CheckBoxElement>;
        }
    }
}

// This interface describes our custom element, holding all its
// available attributes. This should be placed within a .d.ts file.
declare interface CheckBoxElement extends HTMLElement {
    checked: boolean;
}

Respuesta #2

Aquí están los atributos correctos para usar, de lo contrario obtendrás un error al pasar key, por ejemplo.

declare global {
  namespace JSX {
    interface IntrinsicElements {
      'xx-element1': React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>; // Normal web component
      'xx-element2': React.DetailedHTMLProps<React.HTMLAttributes<HTMLInputElement>, HTMLInputElement>; // Web component extended from input
    }
  }
}

Artículos relacionados