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

Property does not exist on the type in vue-class-component #360

Closed
wizardnet972 opened this issue Sep 12, 2019 · 8 comments
Closed

Property does not exist on the type in vue-class-component #360

wizardnet972 opened this issue Sep 12, 2019 · 8 comments

Comments

@wizardnet972
Copy link

I created new vue with typescript application using latest @vue/cli (v3).
When I use component decorator from vue-class-component with computed/props/methods, I got an error:

Property 'count' does not exist on type 'HelloWorld'.Vetur(2339)

image

Here my code:

<script lang="ts">
import { Prop, Vue } from "vue-property-decorator";

import Component from "vue-class-component";

@Component({
  computed: {
    count() {
      return 'blabla';
    }
  }
})
export default class HelloWorld extends Vue {
  @Prop() private msg!: string;

  onClick() {
    const y = this.count;
  }
}
</script>

But according to the example it should be working fine. How do I fix this?

@ReinisV
Copy link

ReinisV commented Sep 12, 2019

From the first example on the landing page
image

You need to write that getter differently.

Unfortunately, decorators (as they are proposed/implemented now) cannot modify the type that they decorate, which is why nothing you ever pass to the decorator will ever show up in a typesafe manner.

And the example that you mention has a workaround added for this specific issue
image

@wizardnet972
Copy link
Author

But why to write the property in two places? :(

@ReinisV
Copy link

ReinisV commented Sep 12, 2019

You write it in one place, within the class body

@Component()
export default class HelloWorld extends Vue {
  @Prop() private msg!: string;

  get count() {
      return 'blabla';
   }

  onClick() {
    const y = this.count;
  }
}

this is the correct, supported and documented vue-class-component way of writing computed properties.

The decorator allows passing various component options to be merged in with the component, but those options do not become typesafe by themselves, because, as I mentioned previously, a decorator cannot modify the type it decorates.

So while your approach works, it does not add typesafety, which, arguably, is the whole point of vue-class-component, which is why the approach I (and the documentation) have specified is the better one and should be used imho.

@wizardnet972
Copy link
Author

@ReinisV
I know that. I have no intention to write getter in component decorator.

I just give example that getter in component is not working with typescript. The real reason is to use mapGetter of vuex in component decorator.
Which is not work. so why I should use vue-class-component at all? when I write one getter in @component and I write another variable in the class. I think is better to use just Vue.extend if this is the case.
What do you think about that?

@ReinisV
Copy link

ReinisV commented Sep 12, 2019

Honestly, I don't know how to work regular old Vuex and it's mapXXX methods in with the vue-class-component.

I'm not saying it is impossible, I've just never tried, because I use class based Vuex wrappers together with my class based Vue wrapper :)

My favorite is vuex-simple.

@ReinisV
Copy link

ReinisV commented Sep 12, 2019

I'm not saying it is impossible, I've just never tried

Not true, now that I think of it, I did write my own set of mapXXX methods specifically to work with any kind of Vuex (I used them with the same vuex-simple, but they could be used with vanilla Vuex too, they just would not provide typesafety).

The logic was that you have a mapXXX method, that you pass a callback that accesses the specific state/getter/action. That method would then read that callback's code, determine the name of that field to get, and store it in the field on the instance.

Then, the custom decorator reads that field name from the instance, and then replaces it with its own getter that is a wrapper for regular old vanilla vuex instance. It does the replacing on an per-instance basis by hooking it's logic into the @Component decorators logic for merging in mixins, I think. The cool part was that with typesafety on, you could make the mapXXX method return the same type as the Vuex method passed in the callback, thus making the whole thing typesafe.

Alas, this was a long time ago and that code was proprietary, so even if I had access to it, I couldn't share it. Thanks capitalism!

when it was used, it looked something like this

@Component()
export default class HelloWorld extends Vue {
  @Prop() private msg!: string;

  @Vuex() count = mapState(s => s.count);

  onClick() {
    const y = this.count;
  }
}

@ReinisV
Copy link

ReinisV commented Sep 12, 2019

I think is better to use just Vue.extend if this is the case.

Off the books, yeah I think it is better to do that.

As you most likely already know, Vue3 promises to have the new functional/hook/whatever api, which will be a lot better for both TypeScript typesafety and Vue development overall, so there won't be much use for classes in Vue component defintions looking into the future.

If I'd be working on new projects, I'd just tide myself over using Vue.extend instead of trying to push classes where they really ought not to be (Vue has always been functional and I started using classes with Vue only because at the time it was better typesafety than Vue.extend).

Vue (or JS for that matter) has never quite fit the box (the box, in this case, is class and object oriented programming).

@ktsn
Copy link
Member

ktsn commented Nov 3, 2019

This is because decorator cannot change the class instance type. You have to declare the property type by yourself or use some decorator like vuex-class to map getters on class properties.

@ktsn ktsn closed this as completed Nov 3, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants