The Wayback Machine - https://web.archive.org/web/20201004102947/https://github.com/vuejs/vue/issues/8721
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 'xxx' does not exist on type CombinedVueInstance ? #8721

Open
SunshowerC opened this issue Aug 28, 2018 · 33 comments
Open

Property 'xxx' does not exist on type CombinedVueInstance ? #8721

SunshowerC opened this issue Aug 28, 2018 · 33 comments
Labels

Comments

@SunshowerC
Copy link

@SunshowerC SunshowerC commented Aug 28, 2018

Version

2.5.17

Reproduction link

Steps to reproduce

  1. use vue-cli init a ts hello-world project .
  2. code like that
<script lang="ts">
import Vue from "vue";
export default Vue.extend({
  name: "HelloWorld",
  props: {
    msg: String
  },
  data():any {
    return {
      wtf: this.initData(), // throw ts error : Property 'initData' does not exist on type 'CombinedVueInstance<Vue, {}, {}, {}, Readonly<{ msg: string; }>>'.
    }
  },
 
  methods: {
    initData():any {
        return {
          a: ''
        }
    },
  },
 
});
</script>

What is expected?

How can i fix it ?

What is actually happening?

Property 'initData' does not exist on type 'CombinedVueInstance<Vue, {}, {}, {}, Readonly<{ msg: string; }>>'.

@SunshowerC SunshowerC changed the title Property 'xxx' does not exist on type CombinedVueInstance Property 'xxx' does not exist on type CombinedVueInstance ? Aug 28, 2018
@ktsn ktsn added the typescript label Aug 28, 2018
@KaelWD
Copy link
Contributor

@KaelWD KaelWD commented Aug 28, 2018

It seems to be intentional, I guess so you can't accidentally access computed properties via a method?

type DataDef<Data, Props, V> = Data | ((this: Readonly<Props> & V) => Data)

edit: 540a38f, #5887 (comment)

@SunshowerC
Copy link
Author

@SunshowerC SunshowerC commented Aug 29, 2018

I don't understand. What bad would happen if i access computed properties via a method ?

@KaelWD
Copy link
Contributor

@KaelWD KaelWD commented Aug 29, 2018

@SunshowerC
Copy link
Author

@SunshowerC SunshowerC commented Aug 29, 2018

Uh... I didn't use computed property, just use a method function, and the methods does exist in data.

image

And I may turn to vue-class-component instead of Vue.extend, the native vue is still not so friendly to typescript (Maybe just because i am not so proficient in vue). Anyway, thanks for helping me.

@KaelWD
Copy link
Contributor

@KaelWD KaelWD commented Aug 29, 2018

Yeah I know, it is a bit silly. Just a guess as to why they might've done that.

@zhuscat
Copy link

@zhuscat zhuscat commented Sep 3, 2018

Same here.

"vue": "^2.5.17"

"typescript": "^3.0.0"

Is there any way to access methods in data function?

@brandoncash
Copy link

@brandoncash brandoncash commented Oct 10, 2018

Since this appears to be only a typing issue and not a runtime issue, there is an (ugly?) workaround available: cast this as type any:

return {
  wtf: (this as any).initData(),
};

Additionally omit the () to store a reference to the method that is executable outside of the current scope, e.g. if you pass it to a child via a prop.

@mms-
Copy link

@mms- mms- commented Oct 20, 2018

Same here. Vue 2.5 has better type declaration support for TypeScript but this seems broken.

@gcollombet
Copy link

@gcollombet gcollombet commented Oct 22, 2018

Same problem for me

@ktsn
Copy link
Member

@ktsn ktsn commented Nov 13, 2018

I guess we should remove this type from data option function and make it as the same as other function this type. The use case that OP provides looks totally valid.

I also faced another use case which I need comprehensive this type in data function when writing some function in it.

data() {
  return {
    someFunc: () => {
      this.someComputed() // `this` type here should be comprehensive
    }
  }
}

As a similar case, this type of beforeCreate seems also to be removed.

But they probably breaks existing apps type checking as we need to explicitly declare data function return type since it no longer infers return type of data due to this restriction. I'm not sure how much the change affects the existing apps...

hedongxiaoshimei added a commit to hedongxiaoshimei/vue-typescript-tsx that referenced this issue Dec 12, 2018
@hedongxiaoshimei

This comment was marked as off-topic.

@JoshZA

This comment was marked as off-topic.

@schnetzi
Copy link

@schnetzi schnetzi commented Aug 20, 2019

Since this appears to be only a typing issue and not a runtime issue, there is an (ugly?) workaround available: cast this as type any:

return {
  wtf: (this as any).initData(),
};

Additionally omit the () to store a reference to the method that is executable outside of the current scope, e.g. if you pass it to a child via a prop.

So is this the proposed solution at the moment?

@danjohnso
Copy link

@danjohnso danjohnso commented Oct 17, 2019

One workaround I had been using is to add an Interface for the Vue instance like this:

interface IComponent {
    $refs: {
        Form: HTMLFormElement;
    };
    InitData(): void;
}

export default (Vue as VueConstructor<IComponent>).extend({
...

This will let you add typing for methods and $refs, does not seem to be any side effects.

EDIT:

I will add this too since I struggled to work with the types for nullable properties (late initialization) with Vue.extend. if you try to return a type | null that is initialized as null, the typings think its literally null and that it cannot be the type. Workaround is to cast the return again, which is annoying so I made a wrapper type. This works well if you have data that needs to be set in mounted, or is a component level data that maybe doesn't get initialized until a certain method is called (Form validator and Dialog reference in UI framework in my cases:

export type Nullable<T> = T | null;

Vue.extend({
    data() {
         const dialog: Nullable<Dialog> = null;

        return {
            dialog: dialog as Nullable<Dialog>
        };
    },
    methods: {
        ButtonClick(): void {
            this.dialog = new Dialog({});
        }
    }
});
@JaidenDeChon
Copy link

@JaidenDeChon JaidenDeChon commented Oct 23, 2019

I had this error while working inside of a computed property. My data and computed were organized like this:

export default Vue.extend({
    name: 'componentName',
    data() {
        return {
            myDataPoint: false,
        };
    },
    computed: {
        trueOrFalse() {
            return this.myDataPoint ? 'is-true' : 'is-false';
        }
    },
})

It would give me the same error (Property myDataPoint does not exist on type CombinedVueInstance...)

However, when I declared what type would be returned by the function, the error went away:
(look to the trueOrFalse computed property for the change)

export default Vue.extend({
    name: 'componentName',
    data() {
        return {
            myDataPoint: false,
        };
    },
    computed: {
        // declare the type returned by your function/computed/method
        trueOrFalse(): string {
            return this.myDataPoint ? 'is-true' : 'is-false';
        }
    },
})

Any time I've run into this error, this is the technique I used to fix it. I hope it helps someone else, too

@douglas-pires
Copy link

@douglas-pires douglas-pires commented Nov 7, 2019

Declare the return type worked for me as well... But such strange behavior.

@stoically
Copy link

@stoically stoically commented Nov 11, 2019

FWIW, the error shows for me only in VSCode, but when compiling with tsc directly, there's no error. Also, when I edit one of the falsely highlighted properties (like deleting one char and putting it back), most of the time the error just goes away.

@jacekkarczmarczyk
Copy link

@jacekkarczmarczyk jacekkarczmarczyk commented Nov 11, 2019

@tenadolanter
Copy link

@tenadolanter tenadolanter commented Nov 14, 2019

Declare the return type worked for me sometimes, but turn to vue-class-component instead of Vue.extend will work awalys!

@daveberning
Copy link

@daveberning daveberning commented Nov 26, 2019

Declare the return type worked for me as well... But such strange behavior.

Same here. Odd behavior but it works nonetheless. I supposed having a return in TypeScript never hurts haha!

@IAMtheIAM
Copy link

@IAMtheIAM IAMtheIAM commented Jan 15, 2020

This happens for all my methods and data properties. What's the solution?

UPDATE: Apparently, you have to annotate the return type for your computed methods, otherwise all your methods and data properties won't appear to typescript as if they are on the CombinedVueInstance. As soon as I did that, all errors went away regarding this.

krmax44 added a commit to krmax44/clef.ninja that referenced this issue Feb 8, 2020
@sceee
Copy link

@sceee sceee commented Feb 17, 2020

Thanks @IAMtheIAM, your hint solved it for me. I was having the issue with methods that called vuex actions - and I thought initially the error might be in the type resolution for the vuex actions somehow. But it turned out I had added another computed property in the component that did not have a return type set. Adding this one solved it for my case.

@tomturton
Copy link

@tomturton tomturton commented Mar 13, 2020

I had this issue until I gave all my computed properties return types.
However, Jest unit tests continued to throw the same TypeScript error.

I had to alter my expectation to follow this pattern:

expect((wrapper.vm as any).subtotalFormatted).toBe('£1,234.56');

Yuk! I hope this can be resolved soon.

kparkov added a commit to NationalMuseumofDenmark/official.frontend.component that referenced this issue Mar 20, 2020
@DarkEye123
Copy link

@DarkEye123 DarkEye123 commented Apr 23, 2020

I have this issue - but 'computed' statement is nowhere in my dummy project. I'm using just 'methods'. Basically reproduction is the same as the original post at the top. I tried the solution with the type declaration, this didn't help me (ts 3.8.3)

@DarkLite1
Copy link

@DarkLite1 DarkLite1 commented May 8, 2020

Having the same issue when using the new Vue.js Composition API with vscode-insiders. The code compiles without TS errors but vscode shows an error nonetheless.

image

// setup(props, context) { 
watch(
    () => context.root.$q.screen.width,
    () => setMiniState(undefined)
)

Details
Version: typescript 3.8.3, eslint 6.8.0

Version: 1.46.0-insider (system setup)
Commit: d487078dc7fc1c276657cadb61b4f63833a8df55
Date: 2020-05-07T16:19:54.327Z
Electron: 7.2.4
Chrome: 78.0.3904.130
Node.js: 12.8.1
V8: 7.8.279.23-electron.0
OS: Windows_NT x64 10.0.14393

Possible related issues: #23987, #29511 #32573 #34999

Type declaration didn't work here either as a workaorund. So this failed too in vscode:

watch(
   (): number => context.root.$q.screen.width,
   () => setMiniState(undefined)
)
@jQrgen
Copy link

@jQrgen jQrgen commented May 14, 2020

I also have this problem in vscode

@KaelWD
Copy link
Contributor

@KaelWD KaelWD commented May 29, 2020

Typescript 3.9 has made this even worse, I have to specify return types for methods too now.

@tipsy
Copy link

@tipsy tipsy commented Jun 6, 2020

I'm very new to TypeScript. I tried all the advice here without any success, but I managed to build on @danjohnso's workaround to "solve" this with intersection types:

export default (Vue as VueConstructor<Vue & Interface1 & Interface2>).extend({

I have no idea if doing that is bad, but everything seems to work fine.

Edit: My issue is with properties from mixins not being recognized.

@morkro
Copy link

@morkro morkro commented Jun 8, 2020

Solution from @tipsy solved it for me. My use case was using mapState.

interface HomeMapState {
  plants: Plant[]
}

export default (Vue as VueConstructor<Vue & HomeMapState>).extend({
  name: 'Home',
  computed: {
    ...mapState<HomeState>('home', {
      plants: (state: HomeState) => state.plants,
    }),
    plantData(): Array<Plant | {}> {
      if (this.loading) {
        return new Array(5).fill({})
      }
      return this.plants
    },
  }
})

this.plants in plantData() was previously always yielding an error and couldn't be found on the Vue instance.

@taylorhoward92
Copy link

@taylorhoward92 taylorhoward92 commented Jun 22, 2020

I'm having this problem with Jest unit tests as well

@r-darwish
Copy link

@r-darwish r-darwish commented Jul 25, 2020

Annotating the computed properties got rid of the error in vscode. However, I still get an error when running yarn build. I had to resort to this ugly hack

@DNature
Copy link

@DNature DNature commented Aug 8, 2020

I had this error while working inside of a computed property. My data and computed were organized like this:

export default Vue.extend({
    name: 'componentName',
    data() {
        return {
            myDataPoint: false,
        };
    },
    computed: {
        trueOrFalse() {
            return this.myDataPoint ? 'is-true' : 'is-false';
        }
    },
})

It would give me the same error (Property myDataPoint does not exist on type CombinedVueInstance...)

However, when I declared what type would be returned by the function, the error went away:
(look to the trueOrFalse computed property for the change)

export default Vue.extend({
    name: 'componentName',
    data() {
        return {
            myDataPoint: false,
        };
    },
    computed: {
        // declare the type returned by your function/computed/method
        trueOrFalse(): string {
            return this.myDataPoint ? 'is-true' : 'is-false';
        }
    },
})

Any time I've run into this error, this is the technique I used to fix it. I hope it helps someone else, too

This does not work with props:
err

@DNature
Copy link

@DNature DNature commented Aug 9, 2020

This does not work with props:

After explicitly typing out the return type of the getHeight() function the errors went away.
I'm glad i found this fix. Thanks to everyone :)
code

3starblaze added a commit to 3starblaze/mini-tomato-timer that referenced this issue Sep 1, 2020
Typescript can't find methods unless computed properties are annotated,
see vuejs/vue#8721
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
You can’t perform that action at this time.
Morty Proxy This is a proxified and sanitized view of the page, visit original site.