Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plans for complete TypeScript support with TS 4.1.0 #1831

Open
ClickerMonkey opened this issue Sep 18, 2020 · 16 comments
Open

Plans for complete TypeScript support with TS 4.1.0 #1831

ClickerMonkey opened this issue Sep 18, 2020 · 16 comments
Labels
enhancement New feature or request types Related to typings only

Comments

@ClickerMonkey
Copy link

ClickerMonkey commented Sep 18, 2020

What problem does this feature solve?

With the introduction of inference from template strings in TS 4.1.0 it will finally be possible to make Vuex completely type safe (validating all types, paths for commit/dispatch/modules/getters, etc).

Are there existing plans to add complete type support with the release of Vuex 4?

For reference, I've created the following project:

https://github.com/ClickerMonkey/vuex-typescript-interface

The only adjustment to the existing type system is that it would require an interface for each module and the root state - so that the modules and root state are aware of each others types. It could be optional like it currently is.

Here's how the new TS feature would solve the remaining challenge with complete type support with Vuex:

type GetEmbeddedType<O, Path extends string> = 
    Path extends `${infer A}/${infer B}` 
    ? A extends keyof O
        ? B extends keyof O[A]
            ? O[A][B]
            : never
        : never
    : never;


interface State {
    prop: {
        innerProp: number;
    }
};

type InnerPropType = GetEmbeddedType<State, 'prop/innerProp'>; // number!!

What does the proposed API look like?

Similar to what exists now, just full type support to validate types, the existence of all mutations and dispatches, and communications between the root store and it' modules.

@kiaking kiaking added proposal types Related to typings only labels Nov 5, 2020
@kiaking
Copy link
Member

kiaking commented Nov 5, 2020

Yes! We're aware of TS 4.1 and this might work. To be honest I was thinking to focus TS on Vuex 5 but this kinda did change things 😅

Let's come back to this issue once TS 4.1 is released, and see how it goes. PR is welcome too! I think there's no harm trying out this feature 👍

Also, I think this can be added to both Vuex 3 & 4...?

@savannahp
Copy link

This would realllyyy help! Instead have to use type any just to get it to compile when it comes to your store.ts file

benjaminrsherman added a commit to quacs/quacs that referenced this issue Jan 27, 2021
Vuex supports accessing modules through a store's state like so:

    let value = store.state.moduleName.value;

Unfortunately, the typing used by Vuex does not include modules as valid
members of the state object.  This causes the Typescript compiler to
report an error even though the module property does exist on the state
object.

An issue has been raised to Vuex, and they plan on resolving the above bug
once Typescript 4.1.0 releases: vuejs/vuex#1831.
Since we likely won't be updating to a version of Vuex which supports the
new typings soon, ts-expect-error directives will suppress this.
@timritzer
Copy link

I have written types to support 95% of the Vuex functionality. Because of some of the API surface I went with a wrapper approach, but the API surface is virtually identical. It supports all the mapper functions, and allows fully typed, checked access including namespaces. Would love some feedback if anyone finds it useful.

https://github.com/timritzer/typed-vuex

It requires TS 4.1 so that the template literal functionality is there, and works best with strict on.

@mohammedzamakhan
Copy link

Any updates for better Typescript support for Vuex 4?

@glen-84
Copy link

glen-84 commented May 13, 2021

Does anyone know how to augment the vuex types to achieve what is shown here:

type VuexOptions<M, N> = {
   namespace?: N,
   mutations: M,
}
 
type Action<M, N> = N extends string ? `${N}/${keyof M & string}` : keyof M
 
type Store<M, N> = {
   dispatch(action: Action<M, N>): void
}
 
declare function Vuex<M, N>(options: VuexOptions<M, N>): Store<M, N>
 
const store = Vuex({
   namespace: "cart" as const,
   mutations: {
      add() { },
      remove() { }
   }
})
 
store.dispatch("cart/add")
store.dispatch("cart/remove")

image

(playground)

Edit: See also the 2nd article Realize Vuex unlimited level type inference (TS 4.1 new feature), which shows support for nested modules.

@Shinigami92
Copy link

Isn't is possible to get something like

store.cart.add.dispatch()
// or
store.cart.mutations.add.dispatch()
// or
store.cart.mutations.add()

This would be a whole new feature request, but would increase the DX by far IMO

@glen-84
Copy link

glen-84 commented May 13, 2021

@Shinigami92 There's direct-vuex, but it seems a bit awkward. This should be part of vuex itself IMO.

@Shinigami92
Copy link

@glen-84 Need to test this out next week. Thanks for pointing to this, didn't know it.

@timritzer
Copy link

Does anyone know how to augment the vuex types to achieve what is shown here:

type VuexOptions<M, N> = {
   namespace?: N,
   mutations: M,
}
 
type Action<M, N> = N extends string ? `${N}/${keyof M & string}` : keyof M
 
type Store<M, N> = {
   dispatch(action: Action<M, N>): void
}
 
declare function Vuex<M, N>(options: VuexOptions<M, N>): Store<M, N>
 
const store = Vuex({
   namespace: "cart" as const,
   mutations: {
      add() { },
      remove() { }
   }
})
 
store.dispatch("cart/add")
store.dispatch("cart/remove")

image

(playground)

Edit: See also the 2nd article Realize Vuex unlimited level type inference (TS 4.1 new feature), which shows support for nested modules.

Ya, absolutely. We use it this way. I'll try to distill it down for you.
I use the above package to accomplish it.

We use modules, so I can't give you examples without modules, but the approach would be similar.

I'll make a small Gist.

@timritzer
Copy link

@glen-84 Here is a sample of how I am doing it: https://github.com/timritzer/typed-vuex-examples
Feel free to ask any questions. It is working great for us, as we are any-free and have full types and auto-complete

@glen-84
Copy link

glen-84 commented May 16, 2021

@timritzer,

Thanks for putting that together. However, I was looking for something that would not require a separate package. I was hoping to be able to augment the existing types to make them enforce the use of specific strings (as derived from the actions, mutations, etc. in each module/sub-module).

@timritzer
Copy link

@glen-84 I mean the only package is a set of types I developed to make everything strongly typed. It's a pretty tiny package, handful of TS files, and no real functionality at run time. It has a few passthrough methods to use inferring the types, but that is it.

Feel free to copy the files and use it not as a package, I don't mind a bit. I just made it a package to follow the pattern everyone uses and make it easy to add and update.

@kadet1090
Copy link

kadet1090 commented May 30, 2021

I've made my own type system that aims to be as non-intrusive as it's possible: https://github.com/kadet1090/vuex-typings for now it's not available as any JS package - I'm looking forward to do so, but I don't want for anyone to depend on something that in the end would not work out.

It supports namespaced and global modules, nested modules and has a lot of helpers - everything should be clearly described in the readme.

@Grawl
Copy link

Grawl commented Aug 30, 2021

@kadet1090 looks cool! please follow this project to finish, can't wait to use it in my projects

@miaulightouch
Copy link

I had wait typing gonna be improved for about one year, there are few related PRs have no chance to be merged.

I'm considering alternatives like pinia or harlem.

@kadet1090
Copy link

I think that there are two issues for creating better typings for vuex:

  • It's virtually impossible to create good types that are backwards compatible with current ones. And that means that they should be optional either opt-in or opt-out.
  • Someone would have to maintain them, and types for vuex are not simple - and cannot be simple because of how vuex works.

I potentially could finish my proposal of types and try to get it merged into core but this seems unlikely, as I'd need some feedback from the maintainers.

@kiaking kiaking added enhancement New feature or request and removed proposal labels Oct 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request types Related to typings only
Projects
None yet
Development

No branches or pull requests

10 participants