Slim.js — это легковесная библиотека для создания веб-компонентов с минимальным синтаксисом и высокой производительностью. В TypeScript интеграция Slim.js требует точного определения типов для компонентов, их свойств и событий, особенно если библиотека не предоставляет собственных деклараций типов. Это позволяет использовать автодополнение, проверку типов и безопасное взаимодействие с компонентами.
Типизация в Slim.js строится вокруг следующих ключевых элементов: компоненты, свойства (props) и события.
Каждый компонент Slim.js реализуется как класс, наследующийся от
Slim или создаваемый через Slim.tag(). В
TypeScript можно задать интерфейс для свойств и методов компонента:
import { Slim } from 'slim-js';
interface MyComponentProps {
title: string;
count?: number;
}
class MyComponent extends Slim<MyComponentProps> {
constructor() {
super();
this.title = 'Пример';
this.count = 0;
}
increment() {
this.count! += 1;
}
}
customElements.define('my-component', MyComponent);
Ключевой момент — указание дженерика
<MyComponentProps>, чтобы TypeScript понимал
структуру свойств. Свойства с ? считаются
необязательными.
Если библиотека не имеет собственных .d.ts файлов, можно
создать их вручную. Для Slim.js это обычно включает три шага:
slim.d.ts в проекте или папке
types.HTMLElementTagNameMap, чтобы компоненты корректно
распознавались как HTML-элементы.Пример декларации:
declare module 'slim-js' {
export class Slim<T = any> extends HTMLElement {
props: T;
update(): void;
}
export function tag(name: string, component: typeof Slim): void;
}
И расширение глобального пространства имён:
declare global {
interface HTMLElementTagNameMap {
'my-component': MyComponent;
}
}
Такой подход обеспечивает типовую проверку при использовании кастомных элементов в TypeScript.
Slim.js поддерживает пользовательские события через стандартный API
CustomEvent. Чтобы задать тип события, создаётся интерфейс
и используем дженерики при вызове dispatchEvent:
interface CounterEventDetail {
value: number;
}
class CounterComponent extends Slim<{ count: number }> {
increment() {
this.props.count += 1;
this.dispatchEvent(new CustomEvent<CounterEventDetail>('countChanged', {
detail: { value: this.props.count },
bubbles: true
}));
}
}
document.querySelector<CounterComponent>('counter-component')?.addEventListener('countChanged', (event) => {
console.log(event.detail.value);
});
Использование дженериков для CustomEvent позволяет
TypeScript проверять доступ к полю detail и его
структуру.
При работе с несколькими компонентами удобно создавать автоматические декларации типов через утилиты. Можно написать скрипт на Node.js, который анализирует компоненты и генерирует соответствующие интерфейсы TypeScript. Это особенно полезно для проектов с динамическими свойствами и большим количеством элементов.
Свойства компонента часто синхронизируются с HTML-атрибутами. Для строгой типизации создаются интерфейсы атрибутов:
interface ButtonProps {
label: string;
disabled?: boolean;
}
class ButtonComponent extends Slim<ButtonProps> {
connectedCallback() {
if (this.hasAttribute('disabled')) this.props.disabled = true;
}
}
Слоты типизируются косвенно через контекст использования, указывая, какие элементы можно вставлять в шаблон. Пример строгой типизации слота:
type SlotContent = HTMLElement | string;
class CardComponent extends Slim<{ header?: SlotContent; body?: SlotContent }> {}
Для масштабных проектов создаётся отдельная папка
types/slim/ с файлами .d.ts для каждого
компонента. Поддерживается структура модулей, чтобы
импорты оставались чистыми:
types/
slim/
index.d.ts
button.d.ts
card.d.ts
В index.d.ts агрегируются все экспортируемые типы:
export * from './button';
export * from './card';
TypeScript автоматически подхватывает эти типы при подключении Slim.js.
<Props> при
наследовании от Slim, чтобы избежать any.HTMLElementTagNameMap для корректной работы
querySelector и автодополнения.CustomEvent<T>
и явные интерфейсы деталей события..d.ts и подключать их через
types в tsconfig.json.Эти подходы обеспечивают строгую типизацию, автодополнение и предотвращают ошибки на этапе компиляции, делая разработку на Slim.js в TypeScript безопасной и удобной.