packages/lit-dev-content/site/docs/v2/components/defining.md
Define a Lit component by creating a class extending LitElement and registering your class with the browser:
@customElement('simple-greeting')
export class SimpleGreeting extends LitElement { /* ... */ }
The @customElement decorator is shorthand for calling customElements.define, which registers a custom element class with the browser and associates it with an element name (in this case, simple-greeting).
If you're using JavaScript, or if you're not using decorators, you can call define() directly:
export class SimpleGreeting extends LitElement { /* ... */ }
customElements.define('simple-greeting', SimpleGreeting);
When you define a Lit component, you're defining a custom HTML element. So you can use the new element like you'd use any built-in element:
<simple-greeting name="Markup"></simple-greeting>
const greeting = document.createElement('simple-greeting');
The LitElement base class is a subclass of HTMLElement, so a Lit component inherits all of the standard HTMLElement properties and methods.
Specifically, LitElement inherits from ReactiveElement, which implements reactive properties, and in turn inherits from HTMLElement.
TypeScript will infer the class of an HTML element returned from certain DOM
APIs based on the tag name. For example, document.createElement('img') returns
an HTMLImageElement instance with a src: string property.
Custom elements can get this same treatment by adding to the
HTMLElementTagNameMap as follows:
@customElement('my-element')
export class MyElement extends LitElement {
@property({type: Number})
aNumber: number = 5;
/* ... */
}
declare global {
interface HTMLElementTagNameMap {
"my-element": MyElement;
}
}
By doing this, the following code properly type-checks:
const myElement = document.createElement('my-element');
myElement.aNumber = 10;
We recommend adding an HTMLElementTagNameMap entry for all elements authored
in TypeScript, and ensuring you publish your .d.ts typings in your npm
package.