I'm using custom-elements aka web-components within Preact. The problem is that Typescript complains about elements not being defined in JSX.IntrinsicElements - in this case a check-box element:
<div className={styles.option}>
    <check-box checked={this.prefersDarkTheme} ref={this.svgOptions.darkTheme}/>
    <p>Dark theme</p>
</div>
Error message (path omitted):
ERROR in MyComponent.tsx
[tsl] ERROR in MyComponent.tsx(50,29)
      TS2339: Property 'check-box' does not exist on type 'JSX.IntrinsicElements'.
I came across the following, unfortunately not working, possible solutions:
I've tried adding the following to my typings.d.ts file:
import * as Preact from 'preact';
declare global {
    namespace JSX {
        interface IntrinsicElements {
            'check-box': any; // The 'any' just for testing purposes
        }
    }
}
My IDE grayed out the import part and IntrinsicElements which means it's not used (?!) and it didn't worked anyway. I'm still getting the same error message.
I've even found a file maintained by google in the squoosh project where they did the following to "polyfill" the support:
In the same folder as the component a
missing-types.d.tsfile with the following content, basically the same setup I have but with aindex.tsfile instead ofcheck-bock.tsand they're using an older TS versionv3.5.3:
declare namespace JSX {
  interface IntrinsicElements {
    'range-input': HTMLAttributes;
  }
}
I'm assuming their build didn't fail so how does it work and how do I properly define custom-elements to use them within preact / react components?
I'm currently using [email protected] and [email protected].
Here are the correct attributes to use, otherwise you will get an error when passing key in for example.
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
    }
  }
}
                        Okay I managed to solve it using module augmentation:
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;
        }
    }
}
Using the HTMLAttributes interface we can tell JSX which attributes are available for our custom-element:
// 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;
}
                        With typescript 4.2.3 and preact 10.5.13, here is what works to define a custom tag name with attributes:
declare module 'preact' {
    namespace JSX {
        interface IntrinsicElements {
            'overlay-trigger': OverlayTriggerAttributes;
        }
    }
}
interface OverlayTriggerAttributes extends preact.JSX.HTMLAttributes<HTMLElement> {
    placement?: string;
}
Differences:
'preact' (must be quoted).JSX.IntrinsicElements value type is an interface that extends HTMLAttributes.preact.JSX.HTMLAttributes.HTMLElement to populate the eventTarget type in props/attrs like event listeners. You could also put SVGElement if applicable.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With