Cory Rylan

My name is . Google Developer Expert, speaker, Software Developer and Web Components enthusiast.

Follow @coryrylan
Preact JS

How to use Web Components in Preact and TypeScript

Cory Rylan

- 3 minutes

Web Components provide a reusable UI component model for the Web. Web Components are created using a combination of several stand-alone technologies such as Custom Elements, Shadow DOM, and HTML templates.

Web Components similar to components in Preact communicate with properties and events. Properties can be set to pass data into a component, and custom events allow the component to pass data back up the component tree.

In this post we will learn how to take a simple alert Web Component and use it in our Preact application written in TypeScript.

A Web Component working in React

To use the alert in our Preact component, we import the component and add the x-alert tag.

import { useState } from 'preact/hooks';
import './alert.js';

export default function App() {
const [show, setShow] = useState(true);

return (
<div>
<button onClick={() => setShow(!show)}>toggle alert</button>

<x-alert hidden={show} status={'status'} closable oncloseChange={() => setShow(!show)}>
This is a Web Component in Preact
</x-alert>
</div>
);
}

If we are using TypeScript, we will likely see errors in our TSX files like this below:

Unknown Web Component in TSX file

TypeScript cannot type check our TSX template due to it not knowing the CustomElement class reference for our custom element tag. We can add our tag to the JSX.IntrinsicElements global interface. This will associate x-alert to the XAlert class reference.

import { useState } from 'preact/hooks';
import { XAlert } from './alert.js';
import './alert.js';

type CustomEvents<K extends string> = { [key in K] : (event: CustomEvent) => void };

type CustomElement<T, K extends string = ''> = Partial<T & { children: any } & CustomEvents<`on${K}`>>;

declare global {
namespace preact.createElement.JSX {
interface IntrinsicElements {
['x-alert']: CustomElement<XAlert, 'closeChange'>;
}
}
}

With Template Literal Types, we can create a list of string types and generate a new list of string types with the on prefix for our events. Next we can pass the event strings to the CustomEvents type, which will adds the function signature . Now we have type checking with custom events for our Web Components in Preact and TSX.

import { useState } from 'preact/hooks';
import { XAlert } from './alert.js';
import './alert.js';

// auto-generate these types using: https://github.com/coryrylan/custom-element-types
type CustomEvents<K extends string> = { [key in K] : (event: CustomEvent) => void };
type CustomElement<T, K extends string = ''> = Partial<T & { children: any } & CustomEvents<`on${K}`>>;

declare global {
namespace preact.createElement.JSX {
interface IntrinsicElements {
['x-alert']: CustomElement<XAlert, 'closeChange'>;
}
}
}

export function App() {
const [show, setShow] = useState(true);

return (
<div>
<button onClick={() => setShow(!show)}>toggle alert</button>

<x-alert hidden={show} status={'success'} closable oncloseChange={() => setShow(!show)}>
This is a Web Component in Preact
</x-alert>
</div>
);
}

With TypeScript Generics and Template Literal Types, we can create an excellent developer experience using Web Components in Preact. If you maintain a Web Component library check out my library custom-element-types which generates type definitions for various frameworks as described in this blog post automatically. Check out the demo below!

View Demo Code   
 

No spam. Short occasional updates on Web Development articles, videos, and new courses in your inbox.

Related Posts

React JS

How to use Web Components with TypeScript and React

Learn how to use Web Components with TSX TypeScript and React components.

Read Article
Lit Web Components

Using Event Decorators with lit-element and Web Components

Learn how to make an event decorator to make it easy to emit custom events with improved type safety in Lit Web Components.

Read Article
TypeScript

Introduction to TypeScript Property Decorators

Learn in this tutorial how to build a TypeScript Property Decorator to create unique IDs for Class properties.

Read Article