TypeScript
@beforesemicolon/web-component is designed with first-class TypeScript support, offering complete type safety for properties, internal state, reference bindings, and custom element interfaces.
Subclassing with Generics
The WebComponent base class accepts two optional generic parameters: Props and State.
1import { WebComponent, html } from '@beforesemicolon/web-component'2 3// 1. Define your component's types4interface ButtonProps {5 label: string6 disabled: boolean7}8 9interface ButtonState {10 clickCount: number11}12 13// 2. Pass them to the WebComponent class14class CustomButton extends WebComponent<ButtonProps, ButtonState> {15 static observedAttributes = ['label', 'disabled']16 17 // Provide default props values as class properties18 label = 'Click me'19 disabled = false20 21 // Provide initial state22 initialState = {23 clickCount: 0,24 }25 26 handleClick = () => {27 this.setState((prev) => ({ clickCount: prev.clickCount + 1 }))28 }29 30 render() {31 // Both this.props and this.state are fully typed!32 return html`33 <button34 onclick="${this.handleClick}"35 disabled="${this.props.disabled}"36 >37 ${() => this.props.label()} (${() => this.state.clickCount()})38 </button>39 `40 }41}Custom Element References
When working with DOM APIs or template references, you often need a reference type that contains both the custom properties of your element and the standard WebComponent / HTMLElement APIs.
The HTMLComponentElement<Props> utility type provides this capability. It combines the WebComponent class with your custom property signatures (without requiring getters) so you can directly read or write values.
1import { HTMLComponentElement } from '@beforesemicolon/web-component'2 3// Given the CustomButton defined above:4type CustomButtonElement = HTMLComponentElement<ButtonProps>5 6// Now you can safely interact with the reference:7const myButton = document.querySelector<CustomButtonElement>('custom-button')8 9if (myButton) {10 // Directly access or update props on the instance11 myButton.label = 'Submit Form'12 myButton.disabled = true13 14 // Standard HTMLElement / WebComponent methods are also available15 myButton.dispatch('custom-event', { detail: 'clicked' })16}Exported Utility Types
The following TypeScript utility types are exported from the library to help build typed component-based architectures:
ObjectInterface<P>
Constraints checking helper representing an object containing key-value pairs where keys must be string, number, or symbol.
1type ObjectInterface<P> = {2 [K in keyof P & (string | symbol | number)]: P[K]3}Props<P>
Maps each key in a properties interface P to a reactive StateGetter from @beforesemicolon/markup. This matches the type of this.props.
1type Props<P> = {2 [K in keyof P]: StateGetter<P[K]>3}PropsSetters<P>
Maps each key in a properties interface P to a reactive StateSetter from @beforesemicolon/markup.
1type PropsSetters<P> = {2 [K in keyof P]: StateSetter<P[K]>3}State<S>
Maps each key in a state interface S to a reactive StateGetter from @beforesemicolon/markup. This matches the type of this.state.
1type State<S> = {2 [K in keyof S]: StateGetter<S[K]>3}StateSetters<S>
Maps each key in a state interface S to a reactive StateSetter from @beforesemicolon/markup.
1type StateSetters<S> = {2 [K in keyof S]: StateSetter<S[K]>3}