Fresh — это современный фреймворк для построения веб-приложений на Deno с акцентом на производительность и рендеринг на стороне сервера. Одним из ключевых аспектов разработки компонентов в Fresh является строгая типизация props, что обеспечивает предсказуемость поведения приложения и уменьшает вероятность ошибок на этапе компиляции.
В Fresh компоненты создаются как функции, возвращающие JSX. Props передаются в компонент как объект параметров. Простейший пример:
interface ButtonProps {
label: string;
disabled?: boolean;
}
export default function Button({ label, disabled }: ButtonProps) {
return (
<button disabled={disabled}>
{label}
</button>
);
}
Ключевой момент: props описываются через интерфейсы или типы TypeScript. Это позволяет:
Props могут быть обязательными или необязательными. Обязательные
props указываются без ?, необязательные — с
?.
interface CardProps {
title: string; // обязательный
subtitle?: string; // необязательный
}
При передаче props TypeScript гарантирует, что обязательные поля присутствуют:
<Card title="Главная страница" /> // корректно
<Card /> // ошибка компиляции
Компоненты часто получают функции через props, например обработчики событий:
interface InputProps {
value: string;
onChange: (value: string) => void;
}
export default function Input({ value, onChange }: InputProps) {
return <input value={value} onIn put={(e) => onChange((e.target as HTMLInputElement).value)} />;
}
Типизация функции позволяет строго определить сигнатуру обработчика и избежать ошибок передачи параметров.
Иногда требуется использовать базовые props и расширять их для других компонентов. В Fresh это делается через наследование интерфейсов:
interface BaseButtonProps {
disabled?: boolean;
}
interface IconButtonProps extends BaseButtonProps {
icon: string;
onClick: () => void;
}
Такой подход улучшает читаемость кода и облегчает повторное использование компонентов.
Для ограниченного набора значений удобно использовать union-тип или enum:
type Size = 'small' | 'medium' | 'large';
interface BadgeProps {
text: string;
size?: Size;
}
export default function Badge({ text, size = 'medium' }: BadgeProps) {
return <span className={`badge-${size}`}>{text}</span>;
}
Использование union-типов обеспечивает проверку корректности значения еще на этапе компиляции и упрощает поддержку кода.
Для props можно задавать значения по умолчанию прямо в параметрах функции компонента:
interface AlertProps {
message: string;
type?: 'info' | 'warning' | 'error';
}
export default function Alert({ message, type = 'info' }: AlertProps) {
return <div className={`alert alert-${type}`}>{message}</div>;
}
Это удобно для создания компонентов с предсказуемым поведением, даже если часть props не передана.
Props могут быть сложными объектами или массивами объектов:
interface User {
id: number;
name: string;
}
interface UserListProps {
users: User[];
}
export default function UserList({ users }: UserListProps) {
return (
<ul>
{users.map(user => <li key={user.id}>{user.name}</li>)}
</ul>
);
}
TypeScript проверяет структуру вложенных объектов, предотвращая ошибки доступа к полям, которых может не быть.
any.Строгая типизация props в Fresh повышает надежность компонентов, упрощает сопровождение кода и уменьшает вероятность ошибок на этапе разработки. Комбинация интерфейсов, union-типов, default-значений и наследования позволяет создавать гибкие и безопасные компоненты, соответствующие современным стандартам TypeScript и практикам frontend-разработки.