How to typecheck a .js file that uses Vue using TypeScript?

Viewed 1330

I have a small .js file using Vue that I want to be type-checked with the TypeScript compiler:

function main() {
    new Vue({
        el: 'ts-message',
        template: '<div>Hello</div>',
    });
}

If I try to typecheck it with tsc, the compiler complains it cannot find the declaration for Vue even though I have the vue npm package installed:

$ tsc --allowJs --checkJs --noEmit src/main.js 
src/main.js:6:9 - error TS2304: Cannot find name 'Vue'.

6     new Vue({
          ~~~

How do I tell the TypeScript compiler to auto-detect the Vue global object or to import it explicitly in the JS file?

Other things I tried

If this main.js file is renamed to main.ts and I add the following line to the top, then the TypeScript compiler succeeds:

import Vue from "vue";

Unfortunately I need to typecheck JavaScript files specifically and I cannot add such a line to the top of a JavaScript file, since browsers do not recognize that kind of import syntax.

4 Answers

Try this:

  1. create a typings/vue.d.ts
// typings/vue.d.ts
import Vue from 'vue'

export as namespace Vue
  1. Include the typings folder in your jsconfig.json:
// jsconfig.json
{
  "include": ["typings"]
}

I have not use Vue.js myself. My assumption is that its typings does not expose Vue globally.

The file above gets the type from vue and expose it as a namespace.

I think you may need to declare the Vue.js via a vue.shims.d.ts file in the main source folder(src folder for example).

Something like this:

declare module "*.vue" {
    import Vue from "vue";
    export default Vue;
}

How do I tell the TypeScript compiler to auto-detect the Vue global object or to import it explicitly in the JS file?

You could do this with a module bundler that invokes the TypeScript compiler, or use a CDN. No manual typings (*.d.ts) are necessary in your case.

Module Bundler

In order to use npm packages in the browser, you need a module bundler (such as Webpack, Rollup, or Parcel) to create a script that includes those packages.

I highly recommend using Vue CLI to automatically scaffold a TypeScript project, which includes Webpack. A few advantages of this generated project:

  • allows using import (or require) in your scripts even when targeting browsers, as the build output would automatically bundle the imported packages
  • minimizes JavaScript fatigue by using sensible defaults that are easily configurable
  • provides IDE support (e.g., via Vetur in Visual Studio Code) that includes automatic type-checking as you code

CDN

If you prefer not to use a module bundler, you could import the third-party scripts from a CDN into the global scope with a <script> tag before your own script runs. For instance, to import Vue and Vue-Router from unpkg, your index.html could contain this:

<script src="https://unpkg.com/vue@2.6.10"></script>
<script src="https://unpkg.com/vue-router@3.0.6"></script>

<script src="./main.js"></script>

new Vue({
  el: '#app',
  data: () => ({
    message: 'Hello Vue.js!',
  }),
})
<script src="https://unpkg.com/vue@2.6.10"></script>

<div id="app">
  <p>{{ message }}</p>
</div>

For vue <= 2.5.17

Create a src/vue.shims.d.ts file with the following content:

import VueConstructor from 'vue';
declare global {
    const Vue: typeof VueConstructor;
}

Then compile it along with the original src/main.js using:

$ tsc --allowJs --checkJs --noEmit src/main.js src/vue.shims.d.ts

It works!

For vue 2.5.18 thru 2.6.10

Open node_modules/vue/types/index.d.ts and comment out the following line:

export as namespace Vue;

replacing it with:

//export as namespace Vue;  // interferes with vue.shims.d.ts

Now you can use the vue.shims.d.ts file mentioned earlier in this answer.

Caution: Modifying a dependency in place is quite a brittle approach. If possible I'd recommend upgrading Vue instead.

For vue > 2.6.10

The development version of Vue has a closed issue and merged PR that makes it possible to use Vue as a global from within a script so long as you explicitly include Vue's types definitions.

Install a development version of Vue:

$ npm install 'git+ssh://git@github.com/vuejs/vue.git#ab50e8e1da2f4f944af683252481728485fedf16'

Now compile the JS script along with the vue/types/index.d.ts file.

$ tsc --allowJs --checkJs --noEmit src/main.js node_modules/vue/types/index.d.ts
Related