Package Exports
- @intescia/ts-plugin-lit-binding-checker
- @intescia/ts-plugin-lit-binding-checker/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@intescia/ts-plugin-lit-binding-checker) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
ts-plugin-lit-binding-checker
A TypeScript Language Service plugin that provides type checking for Lit element templates. It validates property bindings, event handlers, attributes, and slots against your web component definitions.
Features
- Property binding validation — Type-check
.prop=${value}bindings against component properties - Event handler validation — Verify
@event=${handler}matches theCustomEvent<T>type dispatched by the component - Attribute validation — Check static attributes against component properties
- Slot validation — Ensure
slot="name"attributes reference declared slots (@slotJSDoc) - Go to definition — Ctrl+Click on properties and events to jump to their definitions
- Hover information — See property types and event signatures on hover
- CLI tool — Run checks in CI/CD pipelines
Supported Patterns
Scoped Element Registries
Works with both scoped registry implementations:
Open-WC (@open-wc/scoped-elements)
import { ScopedElementsMixin } from '@open-wc/scoped-elements/lit-element.js';
class MyComponent extends ScopedElementsMixin(LitElement) {
static scopedElements = {
'child-element': ChildElement,
};
// or as a getter
static get scopedElements() {
return { 'child-element': ChildElement };
}
}Lit Labs (@lit-labs/scoped-registry-mixin)
import { ScopedRegistryHost } from '@lit-labs/scoped-registry-mixin';
class MyComponent extends ScopedRegistryHost(LitElement) {
static elementDefinitions = {
'child-element': ChildElement,
};
}Event Detection
The plugin automatically detects events from your TypeScript code:
Automatic detection from new CustomEvent()
class MyInput extends LitElement {
private onChange() {
// Plugin detects the event name and infers the detail type
this.dispatchEvent(new CustomEvent('value-changed', {
detail: { value: this.value }
}));
}
}Explicit type annotation
this.dispatchEvent(new CustomEvent<{ value: string }>('value-changed', {
detail: { value: this.value }
}));JSDoc @fires tag (useful for .d.ts files or documentation)
/**
* @fires value-changed - Emitted when value changes with `{ value: string }`.
* @fires selection-changed - Emitted with `{ items: Item[] }`.
*/
class MyInput extends LitElement { ... }Note: For components distributed as
.d.tsdeclaration files, only JSDoc@firestags are available since the source code is not present.
Slot Documentation
Document slots with the @slot JSDoc tag:
/**
* @slot (default) - Default slot for main content.
* @slot header - Slot for header content.
* @slot footer - Slot for footer content.
*/
class MyCard extends LitElement {
render() {
return html`
<slot name="header"></slot>
<slot></slot>
<slot name="footer"></slot>
`;
}
}
## Installation
```bash
npm install -D @intescia/ts-plugin-lit-binding-checkerConfiguration
Add the plugin to your tsconfig.json:
{
"compilerOptions": {
"plugins": [
{
"name": "@intescia/ts-plugin-lit-binding-checker",
"ignoreUndefined": true,
"ignoreAttribute": false,
"ignoreFiles": ["**/*.test.ts", "**/*.spec.ts"]
}
]
}
}Options
| Option | Type | Default | Description |
|---|---|---|---|
ignoreUndefined |
boolean |
false |
Ignore type mismatches caused only by | undefined |
ignoreAttribute |
boolean |
false |
Disable attribute validation (keep only .prop checks) |
ignoreFiles |
string[] |
[] |
Glob patterns for files to exclude from checking |
debugCache |
boolean |
false |
Log cache diagnostics to tsserver log |
VS Code Setup
To use the plugin in VS Code, configure the workspace to use the local TypeScript version:
- Create or edit
.vscode/settings.json:
{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
}- Open a TypeScript file and click on the TypeScript version in the status bar
- Select "Use Workspace Version"
CLI Usage
Run type checking from the command line or in CI:
# Basic usage
npx lit-binding-check tsconfig.json
# With options
npx lit-binding-check tsconfig.json --ignore-undefined --ignore-attribute
# Ignore specific files
npx lit-binding-check tsconfig.json --ignore-files "**/*.test.ts" "**/*.spec.ts"Exit Codes
0— No errors found1— Type errors detected
Error Codes
| Code | Description |
|---|---|
90010 |
Custom element tag not found in scopedElements/elementDefinitions |
90011 |
Property not found on the component class |
90012 |
Property type mismatch |
90020 |
Attribute on unresolved element (warning) |
90021 |
Unknown attribute on component (warning) |
90022 |
Attribute value type mismatch |
90030 |
Event handler type mismatch |
90031 |
Event detail type mismatch (JSDoc-based) |
90032 |
Event not declared on component (warning) |
90040 |
Named slot not declared on component (warning) |
90041 |
Default slot content but no default slot declared (warning) |
Examples
Property Binding Error
class MyPage extends ScopedElementsMixin(LitElement) {
static scopedElements = {
'user-card': UserCard,
};
render() {
return html`
<user-card
.userId=${123} <!-- ✓ OK if userId: number -->
.userName=${"Alice"} <!-- ✗ Error if userName: number -->
></user-card>
`;
}
}Event Handler Error
// UserCard dispatches: CustomEvent<{ id: string }>
// But handler expects: CustomEvent<{ id: number }>
render() {
return html`
<user-card
@user-selected=${(e: CustomEvent<{ id: number }>) => {
// ✗ Error: event detail type mismatch
console.log(e.detail.id);
}}
></user-card>
`;
}Slot Error
// MyCard only declares: @slot header, @slot footer
render() {
return html`
<my-card>
<div slot="header">OK</div>
<div slot="sidebar">✗ Error: slot "sidebar" not declared</div>
</my-card>
`;
}License
MIT