vue
vue copied to clipboard
Property 'xxx' does not exist on type CombinedVueInstance ?
Version
2.5.17
Reproduction link
Steps to reproduce
- use vue-cli init a ts hello-world project .
- 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; }>>'.
It seems to be intentional, I guess so you can't accidentally access computed properties via a method? https://github.com/vuejs/vue/blob/3b43c81216c2e29bd519c447e930d6512b5782e8/types/options.d.ts#L34
edit: https://github.com/vuejs/vue/pull/6391/commits/540a38fb21adb7a7bc394c65e23e6cffb36cd867, https://github.com/vuejs/vue/pull/5887#discussion_r122128852
I don't understand. What bad would happen if i access computed properties via a method ?
They don't exist yet: https://codepen.io/kaelwd/pen/pOErZw?editors=0011
Uh... I didn't use computed property, just use a method function, and the methods does exist in data.

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.
Yeah I know, it is a bit silly. Just a guess as to why they might've done that.
Same here.
"vue": "^2.5.17"
"typescript": "^3.0.0"
Is there any way to access methods in data function?
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.
Same here. Vue 2.5 has better type declaration support for TypeScript but this seems broken.
Same problem for me
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...
vue-tsx-support
👍
Since this appears to be only a typing issue and not a runtime issue, there is an (ugly?) workaround available: cast
thisas typeany: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?
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({});
}
}
});
EDIT: See @IAMtheIAM's answer below
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';
}
},
})
Hope this helps!
Declare the return type worked for me as well... But such strange behavior.
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.
@stoically https://github.com/microsoft/TypeScript/issues/34999?
Declare the return type worked for me sometimes, but turn to vue-class-component instead of Vue.extend will work awalys!
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!
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.
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.
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.
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)
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.

// 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)
)
I also have this problem in vscode
Typescript 3.9 has made this even worse, I have to specify return types for methods too now.
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.
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.
I'm having this problem with Jest unit tests as well