Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Так получилось что изучать 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.