Преобразование типов

Atomico — это современная библиотека для создания веб-компонентов на JavaScript с реактивной системой состояний и декларативным рендерингом. Одним из важных аспектов работы с Atomico является корректная обработка и преобразование типов данных, особенно при работе с свойствами компонентов (props) и событиями.

Типизация свойств компонентов

В Atomico свойства компонентов определяются через props, и правильное указание типов обеспечивает стабильную работу и предотвращает ошибки при передаче данных.

import { c, prop } from "atomico";

function MyComponent() {
    return <host>{String(this.message)}</host>;
}

MyComponent.props = {
    message: prop.string({ default: "Привет, Atomico!" }),
};

Ключевые моменты:

  • prop.string() автоматически приводит значение свойства к строке.
  • Можно указать default значение, которое будет использоваться, если свойство не передано.
  • Atomico поддерживает типы: string, number, boolean, array, object и any.

Преобразование типов при получении свойств

Свойства компонентов могут передаваться через атрибуты HTML. Все атрибуты в DOM изначально строки, поэтому Atomico выполняет автоматическое преобразование типов для соответствия определению свойства.

<MyComponent message="123" />

Даже если message определено как prop.number(), библиотека автоматически преобразует строку "123" в число 123. Если преобразование невозможно, свойство принимает undefined или default значение.

Кастомные преобразования

Иногда стандартные типы недостаточны, и требуется кастомная функция преобразования. Atomico позволяет определять свойство с функцией coerce:

function parseBoolean(value) {
    return value === "true" || value === true;
}

MyComponent.props = {
    isActive: prop.boolean({ coerce: parseBoolean }),
};

coerce вызывается при каждом обновлении свойства и гарантирует, что внутреннее значение компонента соответствует ожидаемому типу.

Преобразование типов при событиях

Atomico использует события на основе DOM (dispatchEvent), которые позволяют компоненту взаимодействовать с внешним миром. Все данные события передаются через detail, и здесь тоже важно учитывать преобразование типов.

function sendValue(value) {
    this.dispatch("update", { detail: Number(value) });
}

Передаваемые данные следует явно преобразовывать в нужный тип, чтобы при обработке события не возникали ошибки. Atomico не делает автоматическое преобразование данных внутри detail.

Влияние реактивности на типы

Atomico отслеживает изменения свойств и состояния компонентов. Если типы изменяются динамически, это может вызвать непредсказуемое поведение. Для безопасного преобразования рекомендуется:

  1. Использовать только заранее определенные типы через prop.
  2. Приводить значения к нужному типу внутри реактивных эффектов:
import { useEffect, useState } from "atomico";

function MyComponent() {
    const [count, setCount] = useState(0);

    useEffect(() => {
        setCount(Number(this.countProp));
    }, [this.countProp]);

    return <host>{count}</host>;
}

MyComponent.props = {
    countProp: prop.any(),
};

Преобразование массивов и объектов

Для массивов и объектов Atomico позволяет использовать prop.array() и prop.object(). При этом можно указать функцию coerce для кастомного преобразования вложенных данных:

MyComponent.props = {
    items: prop.array({
        coerce: value => (Array.isArray(value) ? value : value.split(",")),
    }),
};

Такой подход особенно полезен при передаче данных через атрибуты, которые всегда приходят в виде строки.

Важные рекомендации

  • Всегда определять типы свойств, чтобы избежать неожиданных ошибок при рендеринге.
  • Использовать coerce для сложных преобразований, например, для преобразования строк в объекты или булевы значения.
  • Явно преобразовывать данные при отправке событий, чтобы получатели могли корректно обрабатывать detail.
  • Не полагаться на динамическое приведение типов внутри компонента, это нарушает предсказуемость реактивной системы Atomico.

Применение этих правил обеспечивает корректную типизацию данных и предсказуемое поведение компонентов, что особенно важно при построении больших приложений с множеством взаимодействующих веб-компонентов.