-
Notifications
You must be signed in to change notification settings - Fork 86
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
[feature request] make vuex-class more type safe #2
Comments
I guess this can't be implemented, unfortunately, because decorators can't affect/detect the property's type 😞 |
Well you might be right about affect, but I'm pretty sure it can detect. Because I've seen another library implement such a thing: This library allows you to decorate your component's properties without having to explicitly state which type they are. Here's a snippet from the example code: @vts.component({components: {ChildComponent}})
export default class Example extends Vue {
// props with initializer -> sets default value and type
@vts.prop() aStringPropWithValue = 'abc'
@vts.prop() aNumberPropWithValue = 123
} So that means that library is able to detect the property's type that typescript is inferring it to be, right? |
This example code is doing just infer the property types from the default value. The decorator still does not detect it's type. You can see the |
Ah damn, that's too bad.
|
This guy found a cool solution using functions combined with decorators. :-) |
I'm still a bit confused. Like okay, I'm starting to accept that you can't influence a property's type using a property decorator. However, you do know the "key" to which the property is referring. As in, you know that when someone writes function prop<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}
const doesntMatter = prop(store, propertyName); Not that you are going to use that constant.. the point of that line of code is simply to make TypeScript throw a compilation-error if the property name contains a spelling error. To be honest, I don't really know what I'm talking about and I'm just making guesses here. If I'm saying stupid shit and it annoys you, just let me know. :-) |
I see, we can check spelling error but maybe we need to some changes for API. I also noticed we need to update Vuex's declaration file because it currently does not have the type of getter/action/mutation. I'm considering to implement them but I'm currently too busy by the other jobs. Maybe need 1 week or more 😢 |
I don't mind waiting a week. I'm already really happy that you're willing to look into this. :-) |
I just learned something new while implementing the parentheses-less thingy on that other repo (your explanation was a great help by the way). So yes, a property decorator can't detect the type of the property it is decorating, because it's only getting the target object and the property-name. However, that just so happens to be enough information to then do |
Reflect metadata provides a type information on runtime. So we cannot detect our mistake on compile time. In addition, it does not provide enough information. For example, it always returns foo: null // null type
bar: undefined // undefined type
baz: string | number // union type
qux: { disalbed: boolean } // object type I don't think it's useful for our use case 😞 |
@ktsn export default {
state,
mutations,
getters,
actions
} In our Vue Component , we can declare a instance(myStore) from MyVuexClass , because we had inject the store in root , we also can access state by myStore @StoreComponent( MyVuexClass.SingleInstance) myStore: MyVuexClass
testClick2() {
this.myStore.mutation1 = "123"
this.myStore.mutation2 = 123
this.myStore.action1({param1: "123", param2: 123})
console.log(this.myStore.state1)
console.log(this.myStore.getter1())
} I am new with TypeScript , this is just a imagine, is it possible? 😄 |
Is there any progress? // store/modules/product
export interface ProductState {
name: string
price: number
}
const state: ProductState = {
name: '',
price: 0
} What can I do to know the state type in the Vue component? @State(state => state.product.name) productName // can be inferred to be a string |
Can we also consider adding compile type check instead of relying on typescript type-safe? Like linter or so. Thus we can add it to vue-loader or smth. |
I have been working lately on https://www.npmjs.com/package/vuex-module-decorators |
@championswimmer which features make it better than vue-property-decorator? I don't want to redeclare types above each action, I'm even lazy to append import for annotation, I guess other folks are lazy as I am. |
@Deathangel908 not sure what you mean by
but vuex-module-decorators are for vuex modules while vue-property-decorator is for vue components |
@championswimmer ok, sorry my bad, I see it allows to describe vuex , looks promising. |
That would be great cause currently it cannot detect @action type and always complain about for noimplicitany (or no-explicit-any) |
@championswimmer @ktsn Do you think it’s possible to infer type information from Edit: Solution@namespace('my.store').Action initialize!: store['initialize'] This will lead typescript to infer type information from |
Hello developers. Currently my team is duplicating the type from the actions with a type declaration in a separate files.
This gives us some sort of type checking but it requires upkeep. Do we have a better solution? I've been playing with type intersection in order to declare a type and then intersect it into the Actions declaration. But it's still a WIP. |
I've found a workaround with the help of vuex-module-decorators and For example, I can define my component like this: import Component from 'vue-class-component'
import { namespace } from 'vuex-class'
// This is a store module class defined using vuex-module-decorators
import { Foo } from '~/store/modules/foo'
const foo = namespace('foo')
@Component
export default class App extends Vue {
@foo.State bars: typeof Foo.prototype.bars /// i.e. string[]
@foo.Mutation addBar: typeof Foo.prototype.addBar /// i.e. (bar: string) => void
get barString() {
return this.bars.join(', ') /// <- we should have type check here at compile-time
}
onClick() {
this.addBar(...) /// <- we should have type check here at compile-time
}
} Given that the Foo module is defined like this: import { VuexModule, Module, Mutation } from 'vuex-module-decorators'
@Module({ namespaced: true, name: 'foo' })
export class Foo extends VuexModule {
public bars: string[] = []
@Mutation addBar(bar: string): void {
this.bars = this.bars.concat(bar)
}
@Mutation removeBar(bar: string): void {
this.bars = this.bars.filter(b => b !== bar)
}
} Anyone check this out? |
@frankshaka any benefict for using
import Component from 'vue-class-component'
// This is a store module class defined using vuex-module-decorators
import { Foo } from '~/store/modules/foo'
@Component
export default class App extends Vue {
private readonly foo: getModule(Foo)
get barString() {
return this.foo.bars.join(', ') ; // typesafe
}
onClick() {
this.foo.addBar(...) // typesafe
}
} p.s. your example |
I know it's hard for
Emmm.... Mistyping is truly an issue. But since it's an issue, it may break other things as well, like And, since my definitions like
I think this is off the topic. Our discussions here are to make I definitely know that we can accomplish total "type safety" without using
I don't get what's not working. My example works as expected. |
But what is the point? In your example you have to decorate everything just to bind it. WHy is binding better than accessing the store directly? After all without TypeScript this is exactly what you would do.
Probably. But as long as I have to duplicate declarations (because of technical limitations) the idea of binding is a dead end. I have started out with vuex-class but I think I'll swap it out for vuex-module-decorators or anything else that let's me define the types just once. Sidenote: vuex-module-decorators has some other issues. Sorry! Yet, thanks to ktsn for writing the package and sharing the code. |
Hi! https://gist.github.com/merlosy/16d5251edf082d2f3cfa599ef8c1733f |
I just read a blog post which explained that TypeScript 2.1 has a new feature which makes it possible to type-check the keys of objects. Here's the blog post.
So basically I'm imagining that it should also be possible to do this with vuex, since the store object is just a regular object, right?
So my feature request means that if I have a store like this:
And I have a component like this:
That the type-annotation would make typescript understand that the
count
variable ofMyComp
is a number, since the state variable is a number. And also that typescript would throw an error during compilation, because it can see thatincrement
was misspelled.Do you think you could try to implement that? Even just having one of those two features would already be awesome.
The text was updated successfully, but these errors were encountered: