Поддержка TypeScript

Важное изменение в 2.2.0+ для пользователей TS + Webpack 2

Во Vue 2.2.0+ мы добавили файлы дистрибутивов в формате ES-модулей, которые используются по умолчанию в Webpack 2. К сожалению, это внесло непреднамеренное критичное изменение потому что с TypeScript + Webpack 2 import Vue = require('vue') теперь будет возвращать синтетический объект ES-модуля вместо самого Vue.

Мы планируем обновить все официальные декларации для использования ES-стиля в будущем. Пожалуйста изучите рекомендуемую конфигурацию ниже для корректной настройки на будущее.

Официальные файлы деклараций в NPM-пакетах

Статическая типизация может предотвратить много потенциальных ошибок времени выполнения, особенно при разрастании приложений. По этой причине Vue поставляется с официальными файлами деклараций TypeScript причём не только для ядра Vue, но также для Vue Router и Vuex.

Так как всё это уже опубликовано на NPM, то вам даже не понадобится использовать внешние инструменты, такие как Typings, потому что декларации типов автоматически импортируются вместе с Vue.

Рекомендуемая конфигурация

// tsconfig.json
{
"compilerOptions": {
// ... другие опции опущены
"allowSyntheticDefaultImports": true,
"lib": [
"dom",
"es5",
"es2015.promise"
]
}
}

Обратите внимание на опцию allowSyntheticDefaultImports, которая позволяет использовать следующее:

import Vue from 'vue'

вместо:

import Vue = require('vue')

Первый вариант (синтаксис ES модуля) рекомендуется, потому что это соответствует рекомендациям по использованию ES-модулей, и в будущем мы планируем обновить все официальные декларации для использования экспортов в ES-стиле.

Кроме того, если вы используете TypeScript вместе с Webpack 2, также рекомендуется следующее:

{
"compilerOptions": {
// ... другие опции опущены
"module": "es2015",
"moduleResolution": "node"
}
}

Это сообщает TypeScript оставлять импорты ES-модуля нетронутыми, что в свою очередь позволяет Webpack 2 воспользоваться преимуществами tree-shaking для ES-модулей.

Смотрите также документацию по настройке компилятора TypeScript.

Использование файлов деклараций Vue

Файлы деклараций Vue экспортируют множество полезных деклараций типов. Например, для аннотаций экспортированного объекта опций компонента (например в .vue файле):

import Vue, { ComponentOptions } from 'vue'
export default {
props: ['message'],
template: '<span>{{ message }}</span>'
} as ComponentOptions<Vue>

Компоненты Vue в виде классов

К опциям компонента Vue легко могут быть добавлены аннотации типов:

import Vue, { ComponentOptions } from 'vue'
// Объявляем тип компонента
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 знает, что `this` является типом MyComponent
// и что `this.message` будет строкой
window.alert(this.message)
}
}
// Необходимо явно добавить аннотацию типа MyComponent
// к экспортируемому объекту опций
} as ComponentOptions<MyComponent>

К сожалению, есть несколько ограничений:

К счастью, vue-class-component может решить обе эти проблемы. Это официальная библиотека, которая позволяет объявлять компоненты как нативные классы JavaScript, используя декоратор @Component. В качестве примера давайте перепишем компонент, приведённый выше:

import Vue from 'vue'
import Component from 'vue-class-component'
// декоратор @Component указывает, что класс — это компонент Vue
@Component({
// здесь можно использовать все опции компонента
template: '<button @click="onClick">Click!</button>'
})
export default class MyComponent extends Vue {
// Данные инициализации могут быть объявлены как свойства экземпляра
message: string = 'Hello!'
// Методы компонента могут быть объявлены как методы экземпляра
onClick (): void {
window.alert(this.message)
}
}

С таким альтернативным синтаксисом наши определения компонентов не только более краткие, но также позволяют TypeScript вывести типы message и onClick без необходимости в явном объявлении интерфейса. Такой подход позволяет управлять типами даже для вычисляемых свойств, хуков жизненного цикла и рендер-функций. Для полной информации об использовании смотрите документацию vue-class-component.

Объявление типов для Vue-плагинов

Плагины могут добавлять во Vue новые глобальные свойства, свойства экземпляра и параметры компонента. В этих случаях необходимы декларации типов для возможности плагина компилироваться в TypeScript. К счастью, есть функция TypeScript для расширения существующих типов, называемая расширением модуля (module augmentation).

Например, чтобы объявить свойство экземпляра $myProperty с типом string:

// 1. Обязательно импортируйте Vue перед объявлением расширенных типов
import Vue from 'vue'
// 2. Укажите файл с типами, которые вы хотите расширить
// Vue имеет тип конструктора в types/vue.d.ts
declare module 'vue/types/vue' {
// 3. Объявите расширение для Vue
interface Vue {
$myProperty: string
}
}

После включения указанного выше кода в файл деклараций (например, my-property.d.ts) в вашем проекте, вы можете использовать $myProperty в экземпляре Vue.

var vm = new Vue()
console.log(vm.$myProperty) // Скомпилируется без ошибок

Вы также можете объявить дополнительные глобальные свойства и параметры компонента:

import Vue from 'vue'
declare module 'vue/types/vue' {
// Глобальные свойства можно объявлять
// используя `namespace` вместо `interface`
namespace Vue {
const $myGlobal: string
}
}
// ComponentOptions объявляется в types/options.d.ts
declare module 'vue/types/options' {
interface ComponentOptions<V extends Vue> {
myOption?: string
}
}

Указанные выше объявления позволяют скомпилировать следующий код:

// Глобальное свойство
console.log(Vue.$myGlobal)
// Дополнительный параметр компонента
var vm = new Vue({
myOption: 'Hello'
})