TypeScript типизация

Element Plus — это современная библиотека компонентов для Vue 3, которая полностью совместима с TypeScript. Правильная типизация обеспечивает безопасную работу с компонентами, позволяет получать автокомплешн в IDE и предотвращает большинство ошибок на этапе компиляции. Важно понимать, как использовать типы, интерфейсы и дженерики при работе с Element Plus.


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

Каждый компонент Element Plus предоставляет набор пропсов с чётко определёнными типами. Например, компонент ElButton имеет пропсы:

import { ElButton } from 'element-plus';

const props = {
  type: 'primary' as const,
  size: 'medium' as const,
  disabled: false
};
  • type принимает значения 'primary' | 'success' | 'warning' | 'danger' | 'info' | 'text'.
  • size ограничен 'large' | 'medium' | 'small' | 'mini'.
  • disabled строго boolean.

Использование as const позволяет TypeScript точно выводить литеральные типы, что улучшает автокомплешн и предотвращает передачу некорректных значений.


Интерфейсы для сложных объектов

Многие компоненты, такие как ElTable или ElForm, работают с объектами данных. Типизация таких объектов повышает безопасность и читаемость кода.

Пример для ElTable:

import type { TableColumnCtx } from 'element-plus';

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

const columns: TableColumnCtx<User>[] = [
  { prop: 'id', label: 'ID' },
  { prop: 'name', label: 'Имя' },
  { prop: 'email', label: 'Email' },
  { prop: 'isActive', label: 'Активен' }
];
  • Использование дженерика <User> позволяет строго проверять, что пропсы prop соответствуют ключам объекта User.
  • Ошибки типа prop: 'age' будут обнаружены на этапе компиляции.

События и их типизация

Компоненты Element Plus эмитят события, и их можно типизировать для безопасного использования. Например, ElInput:

import { ref } from 'vue';
import type { InputEmits } from 'element-plus';

const value = ref('');

function handleInput(val: string) {
  value.value = val;
}

<el-input v-model="value" @input="handleInput" />
  • Тип val в handleInput строго string.
  • Для сложных компонентов можно использовать интерфейсы событий, предоставляемые библиотекой, например TableColumnCtx для таблиц.

Типизация через дженерики

Элемент таблицы или селекта часто требует строгой типизации данных. Дженерики помогают сделать код максимально безопасным:

import type { SelectProps } from 'element-plus';

interface Option {
  value: number;
  label: string;
}

const options: Option[] = [
  { value: 1, label: 'Первый' },
  { value: 2, label: 'Второй' }
];

const selectProps: SelectProps<Option> = {
  modelValue: 1,
  options
};
  • Дженерик <Option> гарантирует, что modelValue соответствует типу value объекта Option.
  • Любая попытка передать значение другого типа вызовет ошибку на этапе компиляции.

Компоненты форм и валидация

ElForm и ElFormItem поддерживают строгую типизацию полей и правил валидации:

import type { FormInstance } from 'element-plus';

interface FormData {
  username: string;
  password: string;
}

const formData: FormData = {
  username: '',
  password: ''
};

const rules = {
  username: [{ required: true, message: 'Введите имя пользователя', trigger: 'blur' }],
  password: [{ required: true, message: 'Введите пароль', trigger: 'blur' }]
};

const formRef = ref<FormInstance>();
  • Типизация FormInstance позволяет безопасно вызывать методы validate(), resetFields() и clearValidate().
  • Поля формы строго соответствуют интерфейсу FormData, предотвращая ошибки при доступе к несуществующим свойствам.

Использование утилит TypeScript в Element Plus

Element Plus предоставляет встроенные типы и утилиты, которые можно комбинировать с TypeScript:

  • ComponentPublicInstance — для типизации ссылок на компонент.
  • ExtractPropTypes — для извлечения типов пропсов компонентов:
import type { ExtractPropTypes } from 'vue';
import type { buttonProps } from 'element-plus/es/components/button';

type ButtonProps = ExtractPropTypes<typeof buttonProps>;

const props: ButtonProps = { type: 'success', size: 'small' };
  • Partial и Required — для изменения опциональности пропсов.
  • Readonly — для защиты данных от изменений внутри компонентов.

Взаимодействие с Vue 3 Composition API

Element Plus идеально сочетается с Composition API и TypeScript:

import { ref } from 'vue';
import { ElTable } from 'element-plus';

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

const products = ref<Product[]>([
  { id: 1, name: 'Товар 1', price: 100 },
  { id: 2, name: 'Товар 2', price: 200 }
]);

const selectedProduct = ref<Product | null>(null);
  • ref<Product[]> строго ограничивает массив продуктами.
  • Любая попытка добавить объект с отсутствующими ключами вызовет ошибку TypeScript.

Типизация слотов

Element Plus позволяет строго типизировать слоты с помощью Vue 3 SlotsType:

import type { SlotsType } from 'vue';

interface TableSlots {
  default: { row: Product; index: number };
  header: {};
}

const slots: SlotsType<TableSlots> = {
  default: ({ row, index }) => h('div', `${index}: ${row.name}`),
  header: () => h('div', 'Продукты')
};
  • SlotsType позволяет точно указать, какие данные доступны в каждом слоте.
  • Любая ошибка доступа к несуществующему полю будет обнаружена при компиляции.

Рекомендации по типизации

  • Использовать интерфейсы и дженерики для всех сложных объектов.
  • Применять встроенные типы Element Plus для пропсов, событий и слотов.
  • Всегда использовать as const для литеральных значений.
  • Комбинировать TypeScript утилиты (Partial, Readonly, ExtractPropTypes) для точной типизации.
  • Слоты и формы лучше типизировать через интерфейсы и ref.

Эти подходы позволяют создавать масштабируемый, безопасный и поддерживаемый код на Vue 3 с Element Plus, полностью используя преимущества TypeScript.