Skip to content

Commit 2657341

Browse files
committed
2.5: typescript
1 parent 7615776 commit 2657341

File tree

1 file changed

+40
-84
lines changed

1 file changed

+40
-84
lines changed

src/v2/guide/typescript.md

Lines changed: 40 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -4,117 +4,75 @@ type: guide
44
order: 404
55
---
66

7-
## Important 2.2.0+ Change Notice for TS + webpack 2 users
8-
9-
In Vue 2.2.0+ 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.
10-
11-
We plan to move all official declarations to use ES-style exports in the future. Please see [Recommended Configuration](#Recommended-Configuration) below on a future-proof setup.
7+
> In Vue 2.5.0 we have greatly improved our type declarations to work with the default object-based API. At the same time it introduces a few changes that require upgrade actions. Read [this blog post](https://medium.com/the-vue-point/upcoming-typescript-changes-in-vue-2-5-e9bd7e2ecf08) for more details.
128
139
## Official Declaration in NPM Packages
1410

1511
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 [vuex](https://github.com/vuejs/vuex/tree/dev/types) as well.
1612

1713
Since these are [published on NPM](https://cdn.jsdelivr.net/npm/vue/types/), 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.
1814

15+
We also plan to provide an option to scaffold a ready-to-go Vue + TypeScript project in `vue-cli` in the near future.
16+
1917
## Recommended Configuration
2018

2119
``` js
2220
// tsconfig.json
2321
{
2422
"compilerOptions": {
25-
// ... other options omitted
26-
"allowSyntheticDefaultImports": true,
27-
"lib": [
28-
"dom",
29-
"es5",
30-
"es2015.promise"
31-
]
32-
}
33-
}
34-
```
35-
36-
Note the `allowSyntheticDefaultImports` option allows us to use the following:
37-
38-
``` js
39-
import Vue from 'vue'
40-
```
41-
42-
instead of:
43-
44-
``` js
45-
import Vue = require('vue')
46-
```
47-
48-
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.
49-
50-
In addition, if you are using TypeScript with webpack 2, the following is also recommended:
51-
52-
``` js
53-
{
54-
"compilerOptions": {
55-
// ... other options omitted
23+
// this aligns with Vue's browser support
24+
"target": "es5",
25+
// this enables stricter inference for data properties on `this`
26+
"strict": true,
27+
// if using webpack 2+ or rollup, to leverage tree shaking:
5628
"module": "es2015",
5729
"moduleResolution": "node"
5830
}
5931
}
6032
```
6133

62-
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.
63-
6434
See [TypeScript compiler options docs](https://www.typescriptlang.org/docs/handbook/compiler-options.html) for more details.
6535

66-
## Using Vue's Type Declarations
36+
## Development Tooling
6737

68-
Vue's type definition exports many useful [type declarations](https://github.com/vuejs/vue/blob/dev/types/index.d.ts). For example, to annotate an exported component options object (e.g. in a `.vue` file):
38+
For developing Vue applications with TypeScript, we strongly recommend using [Visual Studio Code](https://code.visualstudio.com/), which provides great out-of-the-box support for TypeScript.
6939

70-
``` ts
71-
import Vue, { ComponentOptions } from 'vue'
72-
73-
export default {
74-
props: ['message'],
75-
template: '<span>{{ message }}</span>'
76-
} as ComponentOptions<Vue>
77-
```
40+
If you are using [single-file components](./single-file-components.html) (SFCs), get the awesome [Vetur extension](https://github.com/vuejs/vetur), which provides TypeScript inference inside SFCs and many other great features.
7841

79-
## Class-Style Vue Components
42+
## Basic Usage
8043

81-
Vue component options can easily be annotated with types:
44+
To let TypeScript properly infer types inside Vue component options, you need to define components with `Vue.component` or `Vue.extend`:
8245

8346
``` ts
84-
import Vue, { ComponentOptions } from 'vue'
47+
import Vue from 'vue'
8548

86-
// Declare the component's type
87-
interface MyComponent extends Vue {
88-
message: string
89-
onClick (): void
90-
}
49+
const Component = Vue.extend({
50+
// type inference enabled
51+
})
9152

92-
export default {
93-
template: '<button @click="onClick">Click!</button>',
94-
data: function () {
95-
return {
96-
message: 'Hello!'
97-
}
98-
},
99-
methods: {
100-
onClick: function () {
101-
// TypeScript knows that `this` is of type MyComponent
102-
// and that `this.message` will be a string
103-
window.alert(this.message)
104-
}
105-
}
106-
// We need to explicitly annotate the exported options object
107-
// with the MyComponent type
108-
} as ComponentOptions<MyComponent>
53+
const Component = {
54+
// this will NOT have type inference,
55+
// because TypeScript can't tell this is options for a Vue component.
56+
}
10957
```
11058

111-
Unfortunately, there are a few limitations here:
59+
Note that when using Vetur with SFCs, type inference will be automatically applied to the default export, so there's no need to wrap it in `Vue.extend`:
11260

113-
- __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.
61+
``` html
62+
<template>
63+
...
64+
</template>
11465

115-
- 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.
66+
<script lang="ts">
67+
export default {
68+
// type inference enabled
69+
}
70+
</script>
71+
```
72+
73+
## Class-Style Vue Components
11674

117-
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:
75+
If you prefer a class-based API when declaring components, you can use the officially maintained [vue-class-component](https://github.com/vuejs/vue-class-componen) decorator:
11876

11977
``` ts
12078
import Vue from 'vue'
@@ -136,9 +94,7 @@ export default class MyComponent extends Vue {
13694
}
13795
```
13896

139-
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).
140-
141-
## Declaring Types of Vue Plugins
97+
## Augmenting Types for Use with Plugins
14298

14399
Plugins may add to Vue's global/instance properties and component options. In these cases, type declarations are needed to make plugins compile in TypeScript. Fortunately, there's a TypeScript feature to augment existing types called [module augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation).
144100

@@ -162,7 +118,7 @@ After including the above code as a declaration file (like `my-property.d.ts`) i
162118

163119
```ts
164120
var vm = new Vue()
165-
console.log(vm.$myProperty) // This will be successfully compiled
121+
console.log(vm.$myProperty) // This should compile successfully
166122
```
167123

168124
You can also declare additional global properties and component options:
@@ -172,9 +128,9 @@ import Vue from 'vue'
172128

173129
declare module 'vue/types/vue' {
174130
// Global properties can be declared
175-
// by using `namespace` instead of `interface`
176-
namespace Vue {
177-
const $myGlobal: string
131+
// on the VueConstructor interface
132+
interface VueConstructor {
133+
$myGlobal: string
178134
}
179135
}
180136

0 commit comments

Comments
 (0)