Pull to refresh

Типизация Vuex 4 на Typescript для Vue 3

Reading time3 min
Views8K

Так получилось что изучать Vue я начал месяц назад с версии Vue 3. Предварительно было заявлено что Vue 3 переписана заново на typescript. Признаться того же самого я ожидал и от новой версии Vuex 4 для Vue 3.

Но почему то все оказалось не так как ожидалось. Посмотрев репозитарий Vuex 4
https://github.com/vuejs/vuex/tree/4.0

Мы неожиданно увидим что он написан на js и в самом конце написаны типы под уже готовый код.

С одной стороны нам как пользователям по идее все равно как написан код - главное чтобы было удобно им пользоваться. И вот тут начинающий пользователь сразу попадает в странную ситуацию при попытке использовать typescript для контроля типов для создаваемых объектов store. Дело в том что типизация создаваемого store в Vuex 4 отсутствует от слова совсем.

Ну да ладно, подумал я и начал искать решение.

Для VUE 2 предлагаются изящные решения на базе декораторов, например, это. Если мы заглянем в исходный код проекта, то увидим что оно разрабатывалось для "vue": ">=2" и "vuex": "3"

Использование декораторов в Vue 3 основано на библиотеке vue-class-component, на которую в наcтоящий момент даже не выпущена документация. Таким образом использование декораторов для типизации Vuex 4 для Vue 3 по моему мнению в настоящий момент выглядит сложной затеей и я решил отказаться от использования декораторов для типизации.

Предлагаемое мной решение основывается на проекте и статье.

Предлагаемый Андреем метод, на мой взгляд, требует большого объема дополнительного кода и на основе его кода я реализовал свое решение.

Основные моменты

Я решил сделать store "одним целым", но с разделением на файлы по признакам общности функций. Соответственно в разных файлах- модулях я предлагаю добавлять к сущностям специальные префиксы. Например для части стора, реализующего авторизацию - auth.ts можно добавлять ко всем функциям префикс auth. Согласен что в таком подходе есть некоторое неудобство - а именно на разработчика ложится контроль за уникальностью имен (но если Вы ошибетесь - то компилятор typescript Вам все скажет).

Такое решение было принято потому что стандартную концепцию модулей Vuex мне типизировать не удалось.

Основная идея заключается в создании новых типов из типов Vuex с помощью Omit и переписывания имеющихся типов Vuex для мутаций, actions и getters.

В репозитарии имеется основной файл store - index.ts и подключаемые файлы (не модули Vuex в стандартном понимании) в которых разрабатывается некая своя логика (в примере это counter и auth).

Для mutatations я несколько упростил задачу и все mutations должны возвращать void. Для Actions я поддержал типизацию payload и значения, возвращаемого action. Типизация выполнена на основе возможности typescript 4 - named tupples. В файлах -примерах я комментариями пометил неизменяемую часть кода, остальной код Вы пишите сами, аналогично неизменяемую часть шаблона выделил в index.

Зависимости

Мой проект компилируется только в среде typescript 4 - обратите внимание на свой package.json.
При создании проекта с помощью vue-cli по умолчанию устанавливается typescript 3 версии версии.

Вам необходимо либо воспользоваться утилитой ncu либо самостоятельно заменить версию в package.json на > 4.0 (на момент написания статьи последняя версия typescript была 4.1.3 ). Ну и конечно же не забудьте удалить файл package-lock.json и запустить команду npm install.

Как пользоваться

Скачайте проект. В директории src Вы найдете папку store - скопируйте ее в свой проект. Проверьте что в Вашем проекте установлен typescript версии >= 4

В файл initialState.ts занесите начальные значение - они же типы для state. Для нормальной типизации state следует учесть, что используется возможность typescript по infer типов из значений. Например, если Вы хотите использовать массив и начальное значение для него планируется пустым - то запишите так - на примере users:

export const initialState = {
  counter: {
    counter: 0,
  },
  auth: {
    name: "Ivan",
    idUser: "89annsdj77",
    email: "ivan@ivan.ru",
    users:[] as Array<string>
  },
};

В основном файле - index.ts подключите Ваши модули согласно приведенному примеру - после строки "no change code " идет не изменяемая часть кода.

В папке modules создайте необходимые Вам файлы - модули с Вашей логикой (это не модули Vuex - это просто разбиение Вашей логики по группам).

Внутри каждого модуля есть неизменная часть кода (шаблон), который должен присутствовать там всегда. Этот шаблон начинается со строки Actions no change code и продолжается до конца модуля.

Далее в каждом модуле Вам необходимо описать типы Getters, ActionsPayload, MutationPayload согласно шаблонам, приведенным в файле counter.ts

Также необходимо реализовать и экспортировать сам функционал mutations, getters, actionsactions

Пример использования стора привел в компоненте HelloWorld.

P.S. мне будет приятно - если Вы поставите моему проекту звездочку на github.

Tags:
Hubs:
+2
Comments0

Articles