Fresh — это современный веб-фреймворк для разработки на Deno, ориентированный на высокую производительность и использование современных возможностей JavaScript и TypeScript. Встроенная поддержка TypeScript делает его особенно удобным для крупных проектов, где важна статическая типизация, автодополнение и безопасность кода.
Fresh изначально поддерживает TypeScript без необходимости
дополнительной конфигурации. Любой файл с расширением .ts
или .tsx автоматически обрабатывается Deno и Fresh. Для
полноценного контроля над компиляцией и настройками проекта используется
файл tsconfig.json.
Пример минимальной конфигурации:
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"strict": true,
"jsx": "react-jsx",
"jsxImportSource": "preact",
"moduleResolution": "Node",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true
},
"exclude": ["node_modules", "dist"]
}
Ключевые моменты:
jsx: "react-jsx" и
jsxImportSource: "preact" — позволяет
использовать JSX с Preact, который лежит в основе Fresh.strict: true — включает строгий режим
TypeScript, обеспечивая полную проверку типов.moduleResolution: "Node" — облегчает
работу с внешними модулями.В Fresh компоненты создаются как функции, возвращающие JSX. Для TypeScript важно корректно типизировать пропсы компонентов.
Пример компонента:
/** @jsx h */
import { h } from "preact";
import { ComponentChildren } from "preact";
interface ButtonProps {
label: string;
onClick: () => void;
}
export default function Button({ label, onClick }: ButtonProps) {
return (
<button onCl ick={onClick}>
{label}
</button>
);
}
Особенности:
ComponentChildren позволяет типизировать дочерние
элементы компонентов.Fresh использует файловую структуру для маршрутов. Файлы в папке
routes автоматически становятся обработчиками
HTTP-запросов. Для TypeScript удобно использовать интерфейсы и типы из
Request и Response.
Пример маршрута:
import { Handlers } from "$fresh/server.ts";
interface Data {
message: string;
}
export const handler: Handlers<Data> = {
GET(req, ctx) {
return new Response(JSON.stringify({ message: "Hello, Fresh!" }), {
headers: { "Content-Type": "application/json" },
});
},
};
Ключевые моменты:
Handlers<Data> обеспечивает типизацию
возвращаемых данных.ctx может содержать информацию о маршруте и контексте
запроса, типизировать его можно с помощью собственных интерфейсов.Fresh поддерживает хранилище состояния через хуки, совместимые с Preact. TypeScript помогает избежать ошибок при работе с состоянием компонентов.
Пример использования состояния:
import { useState } from "preact/hooks";
export default function Counter() {
const [count, setCount] = useState<number>(0);
return (
<div>
<p>Счётчик: {count}</p>
<button onCl ick={() => setCount(count + 1)}>Увеличить</button>
</div>
);
}
Особенности:
<number> указывает тип состояния, предотвращая
случайное присваивание строк или других типов.Fresh полностью совместим с экосистемой Deno. Для сторонних библиотек можно использовать декларации типов, загружаемые через URL или установленные локально.
Пример:
import { oak } from "https://deno.land/x/oak@v12.5.0/mod.ts";
interface ContextState {
user?: string;
}
const app = new oak.Application<ContextState>();
Особенности:
types.interface и type для пропсов компонентов и
данных API.strict: true помогает обнаружить ошибки ещё на этапе
компиляции.paths в tsconfig.json.TypeScript упрощает написание тестов, обеспечивая корректность типов входных и выходных данных:
import { assertEquals } from "https://deno.land/std@0.212.0/testing/asserts.ts";
Deno.test("GET /api returns correct message", async () => {
const res = await fetch("http://localhost:8000/api");
const data = await res.json();
assertEquals(data.message, "Hello, Fresh!");
});
Преимущества:
TypeScript в Fresh обеспечивает строгую типизацию компонентов, маршрутов и состояния, упрощает интеграцию с внешними библиотеками и снижает количество ошибок на этапе разработки. Использование строгого режима, интерфейсов и типовых алиасов делает проект более масштабируемым и поддерживаемым.