25. TypeScript Support
TypeScript Support
Important 2.2 Change Notice for TS + webpack 2 users
In Vue 2.2 we introduced dist files exposed as ES modules, which will be used by default by webpack 2. Unfortunately, this introduced an unintentional breaking change because with TypeScript + webpack 2, import Vue = require('vue')
will now return a synthetic ES module object instead of Vue itself.
We plan to move all official declarations to use ES-style exports in the future. Please see Recommended Configuration below on a future-proof setup.
Official Declaration in NPM Packages
A static type system can help prevent many potential runtime errors, especially as applications grow. That’s why Vue ships with official type declarations for TypeScript - not only in Vue core, but also for vue-router and vuex as well.
Since these are published on NPM, and the latest TypeScript knows how to resolve type declarations in NPM packages, this means when installed via NPM, you don’t need any additional tooling to use TypeScript with Vue.
Recommended Configuration
// tsconfig.json { "compilerOptions": { // ... other options omitted "allowSyntheticDefaultImports": true, "lib": [ "dom", "es5", "es2015.promise" ] } }
Note the allowSyntheticDefaultImports
option allows us to use the following:
import Vue from 'vue'
instead of:
import Vue = require('vue')
The former (ES module syntax) is recommended because it is consistent with recommended plain ES usage, and in the future we are planning to move all official declarations to use ES-style exports.
In addition, if you are using TypeScript with webpack 2, the following is also recommended:
{ "compilerOptions": { // ... other options omitted "module": "es2015", "moduleResolution": "node" } }
This tells TypeScript to leave the ES module import statements intact, which in turn allows webpack 2 to take advantage of ES-module-based tree-shaking.
See TypeScript compiler options docs for more details.
Using Vue’s Type Declarations
Vue’s type definition exports many useful type declarations. For example, to annotate an exported component options object (e.g. in a .vue
file):
import Vue, { ComponentOptions } from 'vue' export default { props: ['message'], template: '<span>{{ message }}</span>' } as ComponentOptions<Vue>
Class-Style Vue Components
Vue component options can easily be annotated with types:
import Vue, { ComponentOptions } from 'vue' // Declare the component's type interface MyComponent extends Vue { message: string onClick (): void } export default { template: '<button @click="onClick">Click!</button>', data: function () { return { message: 'Hello!' } }, methods: { onClick: function () { // TypeScript knows that `this` is of type MyComponent // and that `this.message` will be a string window.alert(this.message) } } // We need to explicitly annotate the exported options object // with the MyComponent type } as ComponentOptions<MyComponent>
Unfortunately, there are a few limitations here:
-
TypeScript can’t infer all types from Vue’s API. For example, it doesn’t know that the
message
property returned in ourdata
function will be added to theMyComponent
instance. That means if we assigned a number or boolean value tomessage
, linters and compilers wouldn’t be able to raise an error, complaining that it should be a string. -
Because of the previous limitation, annotating types like this can be verbose. The only reason we have to manually declare
message
as a string is because TypeScript can’t infer the type in this case.
Fortunately, vue-class-component can solve both of these problems. It’s an official companion library that allows you to declare components as native JavaScript classes, with a @Component
decorator. As an example, let’s rewrite the above component:
import Vue from 'vue' import Component from 'vue-class-component' // The @Component decorator indicates the class is a Vue component @Component({ // All component options are allowed in here template: '<button @click="onClick">Click!</button>' }) export default class MyComponent extends Vue { // Initial data can be declared as instance properties message: string = 'Hello!' // Component methods can be declared as instance methods onClick (): void { window.alert(this.message) } }
With this syntax alternative, our component definition is not only shorter, but TypeScript can also infer the types of message
and onClick
without explicit interface declarations. This strategy even allows you to handle types for computed properties, lifecycle hooks, and render functions. For full usage details, see the vue-class-component docs.
© 2013–2017 Evan You, Vue.js contributors
Licensed under the MIT License.
https://vuejs.org/v2/guide/typescript.html