Конфигурация TypeScript для Preact проектов

Preact является легковесной альтернативой React и отлично сочетается с TypeScript, обеспечивая строгую типизацию и автодополнение при разработке. Конфигурация TypeScript для Preact имеет свои особенности, которые позволяют максимально эффективно использовать возможности фреймворка.

Установка зависимостей

Для корректной работы Preact с TypeScript необходимо установить несколько ключевых пакетов:

npm install preact preact-hooks
npm install --save-dev typescript @types/preact @types/preact-compat
  • preact — основной фреймворк.
  • preact-hooks — поддержка хуков, аналогичных React Hooks.
  • typescript — компилятор TypeScript.
  • @types/preact — типы для Preact.
  • @types/preact-compat — типы для совместимости с React API, если используется совместный код.

Файл tsconfig.json

Основным файлом конфигурации TypeScript является tsconfig.json. Для Preact он должен включать следующие настройки:

{
  "compilerOptions": {
    "target": "ES6",
    "module": "ESNext",
    "lib": ["DOM", "ESNext"],
    "jsx": "react-jsx",
    "jsxImportSource": "preact",
    "moduleResolution": "node",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true
  },
  "include": ["src"]
}

Ключевые моменты конфигурации:

  • "jsx": "react-jsx" — указывает TypeScript использовать современный JSX-трансформер.
  • "jsxImportSource": "preact" — заменяет React на Preact в трансформации JSX.
  • "strict": true — включает строгую типизацию, включая noImplicitAny, strictNullChecks, strictFunctionTypes и другие проверки.
  • "moduleResolution": "node" — необходим для корректного поиска модулей в Node-проектах.
  • "esModuleInterop": true — упрощает импорт CommonJS-модулей.
  • "skipLibCheck": true — ускоряет компиляцию, пропуская проверку типов в сторонних библиотеках.

Организация типов для компонентов

Preact предоставляет типы для функциональных компонентов через FunctionalComponent и JSX.Element. Пример корректной типизации:

import { FunctionalComponent, h } from 'preact';

interface ButtonProps {
  label: string;
  onClick: () => void;
}

const Button: FunctionalComponent<ButtonProps> = ({ label, onClick }) => (
  <button onCl ick={onClick}>{label}</button>
);
  • FunctionalComponent<Props> обеспечивает строгую проверку передаваемых пропсов.
  • Использование interface или type для пропсов позволяет легко расширять и переиспользовать компоненты.

Настройка путей и алиасов

Для крупных проектов полезно настроить пути для импорта модулей:

{
  "compilerOptions": {
    "baseUrl": "./src",
    "paths": {
      "@components/*": ["components/*"],
      "@utils/*": ["utils/*"]
    }
  }
}

Это позволяет использовать:

import Button from '@components/Button';
import { formatDate } from '@utils/date';

Вместо длинных относительных путей.

Поддержка хуков с типизацией

Preact Hooks имеют типы, совместимые с TypeScript. Например:

import { useState, useEffect } from 'preact/hooks';

const Counter: FunctionalComponent = () => {
  const [count, setCount] = useState<number>(0);

  useEffect(() => {
    console.log(`Текущее значение: ${count}`);
  }, [count]);

  return <button onCl ick={() => setCount(count + 1)}>Увеличить: {count}</button>;
};
  • Явное указание типа состояния (useState<number>) повышает точность проверки типов.
  • useEffect корректно работает с массивом зависимостей, обеспечивая статическую проверку.

Интеграция с сборщиками

Vite: один из популярных сборщиков для Preact + TypeScript. Конфигурация vite.config.ts может выглядеть так:

import { defineConfig } from 'vite';
import preact from '@preact/preset-vite';

export default defineConfig({
  plugins: [preact()],
  resolve: {
    alias: {
      react: 'preact/compat',
      'react-dom': 'preact/compat'
    }
  }
});
  • Плагин @preact/preset-vite упрощает настройку JSX-трансформера.
  • Алиасы позволяют использовать библиотеки, ожидающие React, с Preact без изменений.

Рекомендации по строгой типизации

  • Использовать strict режим в tsconfig.json.
  • Явно типизировать все пропсы компонентов.
  • По возможности избегать any и использовать unknown с последующей проверкой.
  • Подключать сторонние библиотеки через типы @types/....

Работа с контекстом

Preact поддерживает контекст аналогично React. Пример:

import { createContext } from 'preact';
import { FunctionalComponent, h } from 'preact';

interface ThemeContextProps {
  theme: 'light' | 'dark';
  toggleTheme: () => void;
}

export const ThemeContext = createContext<ThemeContextProps | undefined>(undefined);

const ThemeProvider: FunctionalComponent = ({ children }) => {
  const [theme, setTheme] = useState<'light' | 'dark'>('light');

  const toggleTheme = () => setTheme(theme === 'light' ? 'dark' : 'light');

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
};
  • createContext<... | undefined> гарантирует, что при использовании контекста TypeScript будет проверять его доступность.

Вывод

Правильная конфигурация TypeScript для Preact обеспечивает строгую типизацию, предсказуемое поведение компонентов и удобную интеграцию с современными сборщиками. Использование strict режима, правильных типов для пропсов и хуков, а также настройка путей и алиасов формирует основу для масштабируемого и безопасного фронтенд-кода.