Using Typescript to define Vuex store types

Attempting to create a TypeScript-friendly Vuex store has been quite the challenge. Following instructions outlined here, I've encountered an issue where accessing this.$store from a component results in a type of Store<any>.

I'm struggling to find a way to make it default to Store<MyState> without needing to cast it every single time.

Answer №1

Regrettably, it is not feasible to replace the existing Store<any> type defined by VueX with a more specific type. One workaround is to introduce a secondary field that provides a properly typed $store, eliminating the need for constant casts or declarations in all components:

import { Store } from "vuex";

// Define $tstore with proper typing equivalent to $store.
// It's impossible to directly override the Store<any> type.
declare module "vue/types/vue" {
  interface Vue {
    $tstore: Store<State>;
  }
}

// Assign $tstore as a getter that returns $store.
Object.defineProperty(Vue.prototype, "$tstore", {
  get: function() {
    return this.$store as Store<State>;
  },
  enumerable: true,
});

Answer №2

If you happen to stumble upon this - we managed to resolve the issue by defining a new type for the constructor's return value -

import Vue, { VueConstructor } from 'vue'
import { Store } from 'vuex'
import { RootState } from '@/store/types'

abstract class CustomVueClass extends Vue {
    public $store!: Store<RootState>
}
const CustomVue = Vue as VueConstructor<CustomVueClass>;

export default CustomVue;

and then simply

export default CustomVue.extend({
    name: 'name',

    components: {
        componentA,
        componentB,
},

this enables us to correctly implement typing:

methods: {
sessionStarted(): Boolean | undefined {
    return this.$store.state.sessionState?.session.started;
},

Answer №3

If you want to ensure typing in your Vue component, one handy way is to declare a property and use the ! operator to let TypeScript know that Vue will handle setting the variable for you. This technique works well with both $refs and $store.

$store!: Store<StoreStateType>;

Another approach is to utilize the MapState or MapGetters component helpers provided by Vuex. These helpers automatically create properties that you can directly use in your template. Here's an example:

@Component({
  computed: mapState({
    userFullName: (state: any) => state.user.fullName,
    userEmail: (state: any) => state.user.email
  })
})

Remember to import necessary dependencies like Store, your Vuex state class, and any helper functions using

import { Store, mapState } from "vuex";
.

Answer №4

I was unable to find a satisfactory answer, so I took matters into my own hands and stumbled upon a fantastic solution. Inside my store.ts file, I simply inserted the following:

declare module "@vue/runtime-core" {
  interface ComponentCustomProperties {
    $store: Store<State>;
  }
}

This snippet transforms the code in this manner:

//store.ts
import { createStore, Store } from "vuex";
import { CustomTool, CustomListType } from "custom";

export type State = {
  tool: CustomTool
  list: CustomListType | null
};

export default createStore({
  state: {
    tool: CustomTool.Empty
    list: null,
  } as State,
  mutations: {},
  actions: {},
  modules: {}
};

declare module "@vue/runtime-core" {
  interface ComponentCustomProperties {
    $store: Store<State>;
  }
}

This solution works perfectly with vue3 and typescript 4.4.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What steps can I take to troubleshoot and fix the issue of a Duplicate identifier 'DateType' error during the React/Typescript building process

Utilizing the MUI library, I have also installed the @mui/x-date-pickers library. In order for my datepicker component to function properly, I need to install the @date-io/date-fns/ library as well. However, upon running yarn build, I encountered the fol ...

Navigating the world of web development can be challenging, especially when trying to

I recently came across a useful tutorial on integrating Symfony with Vue.js, which can be found here: While the tutorial was helpful, I am now looking to implement a specific example from the Vue.js documentation at https://v2.vuejs.org/v2/examples/ into ...

Implementing Vuetify data-table slots for different screen sizes: mobile breakpoints and body

In my Vue component using Vuetify data table, I have the following code: <template slot="body.append"> <tr> <th :colspan="6" class="text-right">Total:</th> </tr> < ...

How can I customize a Vue component slot in Storybook 8.0.6 using Vue 3.4 and Typescript to display various subcomponents within a story?

Incorporating a variety of sub-components into my Vue 3 component based on context is proving to be a challenge. Utilizing slots seems to be the solution in Vue 3, but I'm struggling to make it work within Storybook 8, which I'm using to showcase ...

What is the best way to extract the value from a resolved Promise?

Currently, I am attempting to read a file uploaded by the user and convert it into a String using two functions. The first function is handleFileInput: handleFileInput(event){ setTimeOut(async()=>{ let abcd= await this.convertFileToString(this.fi ...

An informative step-by-step approach to constructing Angular applications utilizing npm and TypeScript

When I first encountered Angular2, I was introduced to TypeScript, npm, and more for the very first time. I was amazed by their power, but I know I've only scratched the surface. While I can navigate through the "development mode," my ultimate goal i ...

Dealing with an unspecified parameter can be tricky - here's how you

Currently, I am in the process of developing an angular application. In this project, there is a specific scenario that needs to be handled where a parameter is undefined. Here's a snippet of my code: myImage() { console.log('test') ...

Open new tab for Angular OAuth2 OIDC login process

Currently, I am incorporating the authorization code flow using angular-oauth2-oidc in my Angular application. It is a fairly straightforward process. However, I would like to have the ability for the login flow to open in a new tab when the login button ...

Use Typescript to access and utilize the value stored in local storage by using the

Trying to retrieve the language setting from localHost and implement it in a translation pipe as shown below: transform(value: string): string {... localStorage.setItem("language", JSON.stringify("en")); let language = JSON.parse(loca ...

Ways to fake an interface using Jest without needing to instantiate it

While Kotlin supports this, I haven't been able to find a way to achieve the same in Jest. My problem arises from having intricate interfaces and arrays of these interfaces where specifying all attribute values is not ideal. Here's an example of ...

Is it possible to duplicate a response before making changes to its contents?

Imagine we are developing a response interceptor for an Angular 4 application using the HttpClient: export class MyInterceptor implements HttpInterceptor { public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<an ...

The type definition file for 'bson' could not be located. It appears to be missing from the program due to being the entry point for the implicit type library 'bson'

I recently set up a new Typescript/React project and encountered the following error in the tsconfig.json file: "Cannot find type definition file for 'bson'. The file is in the program because: Entry point for implicit type library 'bson&ap ...

Setting up Tarui app to access configuration data

I am looking to save a Tauri app's user configuration in an external file. The TypeScript front end accomplishes this by: import {appConfigDir} from "tauri-apps/api/path"; ... await fetch(`${await appConfigDir()}symbol-sets.json`) { ... ...

Differentiating response.data typing on the front end in Typescript depending on the request's success status

Consider this scenario: A secure API authentication route that I am not allowed to access for viewing or editing the code returns interface AuthSuccess { token: string user: object } on response.data if the email and password provided are correct, but ...

After distributing the vue3+vite package, the Component is showing an error due to the absence of a

After publishing a vue3+vite package to npm, I encountered the console warning ""Component is missing template or render function"" when using it in a test project. The component isn't working properly and I'm unable to access its metho ...

Unraveling nested elements with the array map() method in Angular2 and Typescript: Fixing the issue of undefined property reference while mapping

Hey there! I'm currently working with Angular 4 and I have a piece of code that parses data from an API into a TypeScript array of rows. It's important to note that the code functions properly if elements like 'item.tceCampRun' and &apo ...

The Freemode feature in SwiperJS is not functioning properly when used with React TypeScript

Having a slight issue with SwiperJS. Using version 10.1.0 and the following code : import { Swiper, SwiperSlide } from "swiper/react"; import "swiper/css"; export default function Discover() { return ( <> ...

What is the best way to display API error messages to the user?

When a user tries to upload a file that is not an image, I need to display the error message returned from a REST API. The JSON response received from the API will look something like this: { "publicError": "Could not be uploaded, it is not an image! ...

What is the most effective approach for annotating TypeScript abstract classes that are dynamically loaded?

I am in the process of developing a library that allows for the integration of external implementations, and I am exploring the optimal approach to defining types for these implementations. Illustration abstract class Creature { public abstract makeN ...

Switching out a traditional class component with a functional component within a hook to deduce properties from T

One challenge is to subtract props from T within the withHookFn function using a function instead of a class as successfully done in the withHook function. The code contains comments explaining this issue. Dive into the code for more insights. import Reac ...