Фреймворк Fresh использует TypeScript для обеспечения строгой типизации компонентов и обработчиков запросов, что значительно повышает безопасность кода и удобство разработки. Обработчики в Fresh представляют собой функции, которые управляют входящими HTTP-запросами и формируют ответы. Типизация этих функций позволяет явно указывать, какие методы HTTP поддерживаются, какие данные принимаются и возвращаются, а также обеспечивает корректную интеграцию с другими частями приложения.
В Fresh существует несколько ключевых типов обработчиков, которые типизируются с помощью интерфейсов и дженериков:
Handler Основной тип для всех обработчиков. Его сигнатура определяется так:
import type { Handlers } from "$fresh/server.ts";
export const handler: Handlers<DataType> = {
GET(req, ctx) {
// логика обработки GET-запроса
return new Response(JSON.stringify(ctx.state), {
headers: { "Content-Type": "application/json" },
});
},
POST(req, ctx) {
// логика обработки POST-запроса
},
};
Здесь DataType — это тип данных, который будет доступен
в ctx.state. Он позволяет TypeScript проверять структуру
данных на всех этапах обработки запроса.
Request и Response Встроенные объекты
Request и Response полностью совместимы с Web
API, однако типизация позволяет расширять их для удобства. Например,
можно типизировать тело запроса:
interface CreateUserRequest {
name: string;
email: string;
}
export const handler: Handlers = {
async POST(req) {
const data: CreateUserRequest = await req.json();
return new Response(JSON.stringify({ success: true, user: data }));
},
};
Это исключает ошибки при работе с JSON и делает код безопасным и предсказуемым.
Объект ctx предоставляет доступ к состоянию приложения и
параметрам маршрута. Его типизация позволяет гарантировать корректное
использование данных:
interface State {
user?: { id: string; name: string };
}
export const handler: Handlers<State> = {
GET(_req, ctx) {
if (!ctx.state.user) {
return new Response("Unauthorized", { status: 401 });
}
return new Response(`Hello, ${ctx.state.user.name}`);
},
};
Тип State определяет структуру данных, доступных внутри
обработчика, что снижает риск ошибок и облегчает автодополнение в
редакторе кода.
Fresh позволяет определять динамические маршруты с параметрами. Типизация таких параметров выполняется через дженерики:
interface Params {
id: string;
}
export const handler: Handlers<unknown, Params> = {
GET(_req, ctx) {
const userId: string = ctx.params.id;
return new Response(`User ID: ${userId}`);
},
};
Здесь Params описывает все параметры, которые могут быть
извлечены из URL. TypeScript гарантирует, что к ним нельзя обратиться
иначе, чем по определённой структуре.
Обработчики в Fresh могут быть асинхронными. Типизация позволяет корректно работать с промисами и обрабатывать ошибки:
export const handler: Handlers = {
async GET(_req) {
try {
const data = await fetchDataFromDB();
return new Response(JSON.stringify(data));
} catch (error) {
return new Response("Internal Server Error", { status: 500 });
}
},
};
Использование TypeScript позволяет указывать точные типы возвращаемых данных, что помогает при интеграции с фронтендом и другими сервисами.
Fresh поддерживает middleware-подобные функции, которые модифицируют
ctx.state. Типизация позволяет безопасно добавлять новые
свойства:
interface AuthState {
user: { id: string; role: string };
}
export const handler: Handlers<AuthState> = {
GET(_req, ctx) {
if (ctx.state.user.role !== "admin") {
return new Response("Forbidden", { status: 403 });
}
return new Response("Welcome, admin");
},
};
Такой подход предотвращает доступ к несуществующим полям и упрощает рефакторинг кода.
ctx.state и
ctx.params повышает безопасность и предсказуемость
кода.Типизация обработчиков в Fresh превращает серверную логику в строго структурированный и легко поддерживаемый код, позволяя создавать надёжные и масштабируемые приложения на JavaScript и TypeScript.