Utility types

Фреймворк Fresh для JavaScript и TypeScript построен на принципах минимализма и высокой производительности. Одним из ключевых аспектов при работе с TypeScript в Fresh является использование utility types — встроенных типов, которые позволяют гибко манипулировать типами данных и обеспечивать строгую типизацию без избыточного кода.

Utility types особенно полезны для работы с компонентами, маршрутами и данными API, где структуры данных могут быть сложными и динамическими.


Partial<T>

Тип Partial<T> делает все свойства интерфейса или типа необязательными. Это удобно при частичном обновлении состояния компонентов или при работе с объектами, полученными из внешнего API.

Пример:

interface User {
  id: number;
  name: string;
  email: string;
}

const updateUser: Partial<User> = {
  email: "new@example.com"
};

В данном примере объект updateUser может содержать любую комбинацию свойств, включая их отсутствие.

Использование Partial в Fresh:

  • Обновление состояния компонентов в signals.
  • Передача опциональных параметров в серверные функции.

Required<T>

Противоположность Partial. Тип Required<T> делает все свойства типа обязательными. Особенно полезен при строгой валидации данных, когда необходимо гарантировать наличие всех полей.

interface Config {
  host?: string;
  port?: number;
}

const fullConfig: Required<Config> = {
  host: "localhost",
  port: 8080
};

В контексте Fresh это помогает гарантировать корректную инициализацию конфигурации приложения, например, при работе с Deno.env.


Readonly<T>

Тип Readonly<T> делает все свойства объекта только для чтения. Применение этого типа позволяет предотвратить случайное изменение данных, что важно при работе с immutable state и серверным рендерингом.

interface Post {
  id: number;
  title: string;
}

const post: Readonly<Post> = { id: 1, title: "Fresh Guide" };

// post.title = "New Title"; // Ошибка

В Fresh Readonly используется для безопасной передачи пропсов между компонентами без риска их изменения.


Record<K, T>

Record<K, T> создаёт объект с ключами типа K и значениями типа T. Этот utility type незаменим для маппинга данных или создания словарей.

Пример:

type PageRoutes = "home" | "about" | "contact";

const routes: Record<PageRoutes, string> = {
  home: "/",
  about: "/about",
  contact: "/contact"
};

В Fresh это особенно полезно при организации маршрутов и статической генерации страниц.


Pick<T, K> и Omit<T, K>

Эти типы позволяют выбирать или исключать свойства из интерфейсов.

  • Pick<T, K> — выбирает только указанные свойства.
  • Omit<T, K> — исключает указанные свойства.

Пример с Pick:

interface User {
  id: number;
  name: string;
  email: string;
}

type UserPreview = Pick<User, "id" | "name">;

const preview: UserPreview = { id: 1, name: "Alice" };

Пример с Omit:

type UserWithoutEmail = Omit<User, "email">;

const user: UserWithoutEmail = { id: 1, name: "Bob" };

Использование в Fresh:

  • Создание безопасных пропсов для компонентов.
  • Формирование DTO для API без лишних полей.

Exclude<T, U> и Extract<T, U>

Эти utility types работают с сочетаниями типов.

  • Exclude<T, U> исключает типы, содержащиеся в U.
  • Extract<T, U> оставляет только те типы, которые присутствуют в U.

Пример:

type Status = "active" | "inactive" | "pending";

type ActiveStatus = Exclude<Status, "inactive">; // "active" | "pending"
type PendingStatus = Extract<Status, "pending" | "inactive">; // "inactive" | "pending"

В Fresh полезно для строгой типизации состояний компонентов или событий.


NonNullable<T>

Удаляет null и undefined из типа.

type OptionalString = string | null | undefined;
type StringOnly = NonNullable<OptionalString>; // string

Используется при обработке данных из API, чтобы гарантировать, что значения всегда присутствуют.


ReturnType<T> и Parameters<T>

  • ReturnType<T> возвращает тип результата функции.
  • Parameters<T> возвращает кортеж типов аргументов функции.

Пример:

function fetchUser(id: number) {
  return { id, name: "Alice" };
}

type UserType = ReturnType<typeof fetchUser>; // { id: number; name: string; }
type ArgsType = Parameters<typeof fetchUser>; // [number]

В Fresh помогает при строгой типизации хендлеров маршрутов и серверных функций.


Комбинирование utility types

Utility types можно комбинировать для достижения сложной типовой логики. Например:

interface Product {
  id: number;
  name: string;
  price?: number;
}

type ReadonlyPartialProduct = Readonly<Partial<Product>>;

const product: ReadonlyPartialProduct = { name: "Laptop" };
// product.name = "Phone"; // Ошибка

Такое сочетание делает объект одновременно необязательным и неизменяемым, что полезно для безопасной работы с пропсами и API ответами.


Utility types в Fresh являются основой безопасной и гибкой работы с данными. Их применение минимизирует количество ошибок на этапе компиляции, повышает читаемость кода и упрощает поддержку проекта. Комплексное владение Partial, Required, Readonly, Record, Pick, Omit, Exclude, Extract, NonNullable, ReturnType и Parameters позволяет создавать приложения с чистой архитектурой и строгой типизацией.