Fresh — это современный веб-фреймворк для JavaScript и Deno, ориентированный на высокую производительность и использование серверного рендеринга. Типизация компонентов в Fresh играет ключевую роль для обеспечения надежности кода, предотвращения ошибок на этапе компиляции и улучшения автодополнения в редакторах кода. В основе Fresh лежит использование TypeScript, что позволяет строго определять интерфейсы и свойства компонентов.
В Fresh компоненты могут принимать props — объект с параметрами, который задает поведение или отображение компонента. Типизация props осуществляется с помощью интерфейсов или типов TypeScript.
interface ButtonProps {
label: string;
disabled?: boolean;
onClick?: () => void;
}
export default function Button({ label, disabled = false, onClick }: ButtonProps) {
return (
<button disabled={disabled} onCl ick={onClick}>
{label}
</button>
);
}
Ключевые моменты:
label — обязательное свойство строкового типа.disabled — необязательное свойство, по умолчанию
false.onClick — необязательная функция-обработчик
событий.Использование интерфейсов позволяет редактору выдавать автодополнение и проверку типов ещё до запуска приложения.
Fresh использует JSX, что требует корректного
определения типов возвращаемого значения компонента. В TypeScript для
этого используется тип JSX.Element:
import { JSX } from "preact";
interface CardProps {
title: string;
content: string;
}
export default function Card({ title, content }: CardProps): JSX.Element {
return (
<div class="card">
<h2>{title}</h2>
<p>{content}</p>
</div>
);
}
Объявление возвращаемого типа как JSX.Element позволяет
TypeScript точно знать, что функция возвращает корректный JSX,
совместимый с Preact, который лежит в основе Fresh.
Для интерактивных компонентов важно корректно типизировать события и ссылки на элементы DOM. Fresh совместим с Preact-стилем событий:
interface InputProps {
value: string;
onInput: (e: Event) => void;
}
export default function TextInput({ value, onInput }: InputProps): JSX.Element {
return <input type="text" value={value} onIn put={onInput} />;
}
Event — базовый тип события. Для более точной типизации
можно использовать InputEvent или
KeyboardEvent.ref также типизируется через
RefObject:import { useRef } from "preact/hooks";
export default function FocusableInput() {
const inputRef = useRef<HTMLInputElement>(null);
function focus() {
inputRef.current?.focus();
}
return <input ref={inputRef} />;
}
Fresh поддерживает серверные компоненты, которые выполняются только на сервере и могут использовать асинхронные данные. Типизация props и возвращаемого значения также применима для серверных компонентов:
interface UserProfileProps {
userId: string;
}
export default async function UserProfile({ userId }: UserProfileProps): Promise<JSX.Element> {
const response = await fetch(`https://api.example.com/users/${userId}`);
const user = await response.json();
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}
Использование Promise<JSX.Element> гарантирует
корректную работу с асинхронными компонентами.
TypeScript позволяет создавать более сложные структуры типов,
комбинируя интерфейсы и типы с помощью Partial,
Pick, Omit и других утилит:
interface BaseProps {
id: string;
className?: string;
}
interface ButtonProps extends BaseProps {
label: string;
onClick: () => void;
}
type OptionalButtonProps = Partial<ButtonProps>;
Partial<ButtonProps> делает все свойства
необязательными.Pick<ButtonProps, "label" | "onClick"> позволяет
выбрать только определенные свойства.Omit<ButtonProps, "className"> исключает свойство
из типа.Эти утилиты помогают создавать универсальные и повторно используемые компоненты.
Компоненты в Fresh могут принимать вложенные элементы через
children. Тип children в Fresh описывается как
JSX.Element | JSX.Element[]:
interface ContainerProps {
children: JSX.Element | JSX.Element[];
}
export default function Container({ children }: ContainerProps): JSX.Element {
return <div class="container">{children}</div>;
}
Такое определение позволяет компоненту корректно отображать один или несколько дочерних элементов.
Promise<JSX.Element> для серверных компонентов.ref, чтобы избежать
runtime-ошибок.children, чтобы компоненты могли безопасно
обрабатывать вложенные элементы.Типизация компонентов в Fresh не только повышает надежность кода, но и облегчает его сопровождение, создавая строгую контрактную структуру между компонентами и их потребителями.