'Resolve "Property does not exist on type 'Vue'" error

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?

main.ts

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
    }
  }
})

tsconfig

{
  "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"
  ]
}

webpack.config.js

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')
    }
}


Solution 1:[1]

I had the same problem but with exporting component. Some vs code snippets create template without necessary typo 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 exporting component with defineComponent() function

Solution 2:[2]

Adding another answer to bring together several things you may need to fix.

Ensure you include the ".vue" extension in the filename being imported

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.

Add a shim typings file

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;
}

Try different locations for the shim file.

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.

Solution 3:[3]

I was trying to follow this page https://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) }
    })

Solution 4:[4]

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.
  }
}

Solution 5:[5]

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
  }

add return type String.

  computed: {
containerClass(): String {
    return this.isLastChild
  }

Solution 6:[6]

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;

Solution 7:[7]

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
    }
  }
})

Solution 8:[8]

do not use any

use Object.assign(vm, source); instead

like

const source= {count: this.count }
Object.assign(this, source);

Solution 9:[9]

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 enter image description here

"vetur.experimental.templateInterpolationService": false

It works for me

Solution 10:[10]

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;
    },
  }
});