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:
- 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.
- 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.tscon el siguiente contenido, básicamente la misma configuración que tengo pero con un archivoindex.tsen lugar decheck-bock.tsy están usando una versión anterior de TSv3.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
}
}
}
