Reputation: 3633
I am using Typescript with Vuejs to build an application. I have several stand alone components (.vue) files that I am importing into a Typescript (.ts) file. In the Typescript file, I am importing Vue from the npm Vue library and then creating a new Vue to display my components. The error that I am seeing is:
Property x does not exist on type 'Vue'
My build system is Webpack with tsc. Why am I getting this error and how can I resolve it?
import Vue from 'vue';
import Competency from '../components/competency.vue';
new Vue({
el: "#app",
components: {
'competency': Competency
},
data:{
count: 0
},
methods:{
initialize: function(){
this.count = count + 1; // Errors here with Property count does not exist on type vue
}
}
})
{
"compilerOptions": {
// "allowJs": true,
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"lib": [
"es2015",
"dom",
"es2015.promise"
],
"module": "es2015",
"moduleResolution": "node",
"noEmitOnError": true,
"noImplicitAny": false,
//"outDir": "./build/",
"removeComments": false,
"sourceMap": true,
"target": "es5"
},
"exclude": [
"./node_modules",
"wwwroot",
"./Model"
],
"include": [
"./CCSEQ",
"./WebResources"
]
}
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: {
Evaluations: './WebResources/js/main.ts'
},
devServer: {
contentBase: './dist'
},
module: {
rules: [{
test: /\.ts$/,
exclude: /node_modules|vue\/src/,
loader: 'ts-loader',
exclude: /node_modules/,
options: {
appendTsSuffixTo: [/\.vue$/]
}
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
esModule: true
}
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
},
]
},
resolve: {
extensions: [".tsx", ".ts", ".js"],
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
filename: 'Evaluations.html',
template: './WebResources/html/Evaluations.html'
}), new HtmlWebpackPlugin({
filename: 'ExpenseUpload.html',
template: './WebResources/html/ExpenseUpload.html'
}), new webpack.optimize.CommonsChunkPlugin({
name: 'WebAPI'
})
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
}
Upvotes: 51
Views: 124424
Reputation: 988
Have the same issue. Solution is to add a return type on each computed variable.
Issue from this code, without return type.
computed: {
containerClass() {
return this.isLastChild
},
},
Adding the return type String
:
computed: {
containerClass(): String {
return this.isLastChild
},
},
Upvotes: 9
Reputation: 109
In VSCode this was fixed for me by quitting VSCode completely and opening it again.
Upvotes: 0
Reputation: 3762
I had the same problem but with exporting a component. Some vs code snippets create templates without necessary types like this below
export default {
data() {
return {
x: "something",
};
},
methods: {
rename(name: string) {
this.x = name;
},
},
};
The problem was I did not add defineComponent()
to export default. So should be
import { defineComponent } from "vue";
export default defineComponent({
data() {
return {
x: "something",
};
},
methods: {
rename(name: string) {
this.x = name;
},
},
});
Make sure you are exporting the component with the defineComponent()
function.
Upvotes: 30
Reputation: 9411
Adding another answer to bring together several things you may need to fix.
While both
import Competency from '../components/competency';
and
import Competency from '../components/competency.vue';
may compile successfully, the second one will help avoid the error appearing in some IDE's such as VS Code.
As @May pointed out above, you need a file that imports and re-exports the type of "Vue". In @May's answer, it is named vue-file-import.d.ts
, but elsewhere on the internet it is commonly called vue-shim.d.ts
. Regardless of name, the content needed is the same:
// vue-file-import.d.ts
declare module "*.vue" {
import Vue from "vue";
export default Vue;
}
Originally I put it in /src
. I found this had an odd effect. Sometimes it worked, i.e. the VS Code error messages disappeared; and other times it didn't, they reappeared. This happened dynamically as I moved around the project editing different files.
I later found the suggestion for a shim file of identical content, but to be placed in /typings
. I tried this and it worked consistently. Other people seem quite happy with the /src
location.
Upvotes: 10
Reputation: 1804
I was trying to follow this page https://v2.vuejs.org/v2/guide/routing.html and was getting the same TypeScript errors, I fixed it by casting the Vue instance to type any like this
new Vue({
el: '#app',
data: {
currentRoute: window.location.pathname
},
computed: {
ViewComponent() {
return routes[(this as any).currentRoute] || routes['/']
}
},
render (h) { return h((this as any).ViewComponent) }
})
Upvotes: 2
Reputation: 11
If you are using typescript & vue2, you should use Vue.component
or Vue.extend
to define component.
import Vue from 'vue'
const Component = Vue.extend({
...
})
Upvotes: 1
Reputation: 71
@sherwin water's answer help me a lot. I recognized that, once I added a computed
field, the error appears. The solution is simple: add return type for the computed field.
// wrong
computed: {
someThing() {
const { a, b } = this;
return a + b;
}
}
// correct
computed: {
someThing(): number {
const { a, b } = this;
return a + b;
}
}
Upvotes: 6
Reputation: 828
I faced this error when I'm using VS Code editor.
I've installed Vetur plugin on vs code, Vetur handles vue file as typescript file, so I've fixed it to edit settings.json file
Please find this file on your VS editor in your project root directory, then set change like the below
"vetur.experimental.templateInterpolationService": false
It works for me
Upvotes: 0
Reputation: 9
do not use any
use Object.assign(vm, source);
instead
like
const source= {count: this.count }
Object.assign(this, source);
Upvotes: 0
Reputation: 36
Try using Typescript's generics. See https://www.typescriptlang.org/docs/handbook/generics.html
new Vue<{ count: number }, { initialize: () => void }, {}, {}>({
//...
data:{
count: 0
},
methods:{
initialize: function() {
this.count = count + 1;
},
}
});
Upvotes: -1
Reputation: 12228
I suggest using class based components when using typescript (have a look at this "Writing Class-Based Components with Vue.js and TypeScript"). This is the only way to have type safe code and use autocomplete functionality of your IDE
You need to install vue-property-decorator
Here is an example of class based component:
import { Component, Vue, Watch } from 'vue-property-decorator'
@Component({
props: {
prop1: { type: Number }
}
})
export default class MyComponent extends Vue {
// This is how you define computed
get myComputedRoute() {
return this.$route.params;
}
@Watch('myComputedRoute')
onPropertyChanged(value: string, oldValue: string) {
// Do stuff with the watcher here.
}
}
Upvotes: 1
Reputation: 69
I got the same errors with vue 2.8.2 and Typescript 2.5.3. I fixed it by holding my Vue instance in a variable then giving it a type. This ensures TS will know about all Vue properties when you instatiate it using an options object.
var VueApp: any = Vue;
var App = new VueApp({
el: "#app",
data() {
return {
count: 0
}
},
methods:{
initialize() {
this.count = count + 1; // Should work now
}
}
})
Upvotes: 0
Reputation: 1
I ran into similar problems (especially in .vue files). I did find that this seemed to fix the problem however. Anywhere you import .vue files, change the ES6 style "import" to "require" instead.
So in your example, change:
import Competency from '../components/competency.vue';
to...
declare var require: any;
var Competency = require("../components/competency.vue").default;
Upvotes: 0
Reputation: 114
vue-file-import.d.ts
declare module "*.vue" {
import Vue from "vue";
export default Vue;
}
Upvotes: 9