diff --git a/src/images/typescript-type-error.png b/src/images/typescript-type-error.png new file mode 100644 index 0000000000..750d8a0648 Binary files /dev/null and b/src/images/typescript-type-error.png differ diff --git a/src/v2/guide/comparison.md b/src/v2/guide/comparison.md index 73c947a944..09d57bd4ec 100644 --- a/src/v2/guide/comparison.md +++ b/src/v2/guide/comparison.md @@ -1,7 +1,7 @@ --- title: Comparison with Other Frameworks type: guide -order: 28 +order: 29 --- This is definitely the most difficult page in the guide to write, but we do feel it's important. Odds are, you've had problems you tried to solve and you've used another library to solve them. You're here because you want to know if Vue can solve your specific problems better. That's what we hope to answer for you. diff --git a/src/v2/guide/join.md b/src/v2/guide/join.md index 1fef6c8516..93447c8645 100644 --- a/src/v2/guide/join.md +++ b/src/v2/guide/join.md @@ -1,7 +1,7 @@ --- title: Join the Vue.js Community! type: guide -order: 29 +order: 30 --- Vue's community is growing incredibly fast and if you're reading this, there's a good chance you're ready to join it. So... welcome! diff --git a/src/v2/guide/migration-vue-router.md b/src/v2/guide/migration-vue-router.md index 945f4e044d..d9d63c6a0d 100644 --- a/src/v2/guide/migration-vue-router.md +++ b/src/v2/guide/migration-vue-router.md @@ -1,7 +1,7 @@ --- title: Migration from Vue Router 0.7.x type: guide -order: 26 +order: 27 --- > Only Vue Router 2 is compatible with Vue 2, so if you're updating Vue, you'll have to update Vue Router as well. That's why we've included details on the migration path here in the main docs. For a complete guide on using the new Vue Router, see the [Vue Router docs](http://router.vuejs.org/en/). diff --git a/src/v2/guide/migration-vuex.md b/src/v2/guide/migration-vuex.md index 28d89543db..1e5aa28bdf 100644 --- a/src/v2/guide/migration-vuex.md +++ b/src/v2/guide/migration-vuex.md @@ -1,7 +1,7 @@ --- title: Migration from Vuex 0.6.x to 1.0 type: guide -order: 27 +order: 28 --- > Vuex 2.0 is released, but this guide only covers the migration to 1.0? Is that a typo? Also, it looks like Vuex 1.0 and 2.0 were released simultaneously. What's going on? Which one should I use and what's compatible with Vue 2.0? diff --git a/src/v2/guide/migration.md b/src/v2/guide/migration.md index 5640d256d4..266ee20820 100644 --- a/src/v2/guide/migration.md +++ b/src/v2/guide/migration.md @@ -1,7 +1,7 @@ --- title: Migration from Vue 1.x type: guide -order: 25 +order: 26 --- ## FAQ diff --git a/src/v2/guide/typescript.md b/src/v2/guide/typescript.md new file mode 100644 index 0000000000..5bfaa33c25 --- /dev/null +++ b/src/v2/guide/typescript.md @@ -0,0 +1,98 @@ +--- +title: TypeScript Support +type: guide +order: 25 +--- + +## Official Declaration Files + +A static type system can help prevent many potential runtime errors, especially as applications grow. That's why Vue ships with [official type declarations](https://github.com/vuejs/vue/tree/dev/types) for [TypeScript](https://www.typescriptlang.org/) - not only in Vue core, but also [for Vue Router](https://github.com/vuejs/vue-router/tree/dev/types) and [for Vuex](https://github.com/vuejs/vuex/tree/dev/types) as well. + +Since these are [published on NPM](https://unpkg.com/vue/types/), you don't even need external tools like `Typings`, as declarations are automatically imported with Vue. That means all you need is a simple: + +``` ts +import Vue = require('vue') +``` + +Then all methods, properties, and parameters will be type checked. For example, if you misspell the `template` component option as `tempate` (missing the `l`), the TypeScript compiler will print an error message at compile time. If you're using an editor that can lint TypeScript, such as [Visual Studio Code](https://code.visualstudio.com/), you'll even be able to catch these errors before compilation: + +![TypeScript Type Error in Visual Studio Code](/images/typescript-type-error.png) + +### Compilation Options + +Vue's declaration files require the `--lib DOM,ES2015.Promise` [compiler option](https://www.typescriptlang.org/docs/handbook/compiler-options.html). You can pass this option to the `tsc` command or add the equivalent to a `tsconfig.json` file. + +### Accessing Vue's Type Declarations + +If you want to annotate your own code with Vue's types, you can access them on Vue's exported object. For example, to annotate an exported component options object (e.g. in a `.vue` file): + +``` ts +import Vue = require('vue') + +export default { + props: ['message'], + template: '{{ message }}' +} as Vue.ComponentOptions +``` + +## Class-Style Vue Components + +Vue component options can easily be annotated with types: + +``` ts +import Vue = require('vue') + +// Declare the component's type +interface MyComponent extends Vue { + message: string + onClick (): void +} + +export default { + template: '', + 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 Vue.ComponentOptions +``` + +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 our `data` function will be added to the `MyComponent` instance. That means if we assigned a number or boolean value to `message`, 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](https://github.com/vuejs/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: + +``` ts +import Vue = require('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: '' +}) +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](https://github.com/vuejs/vue-class-component#vue-class-component).