Close
升级到 Vue 3 | Vue 2 EOL

TypeScript 支持

Vue CLI 提供内置的 TypeScript 工具支持。

官方声明在 NPM 包中

静态类型系统可以帮助防止许多潜在的运行时错误,尤其是在应用程序不断增长的情况下。这就是为什么 Vue 附带了 官方类型声明 用于 TypeScript - 不仅在 Vue 核心,而且还包括 vue-routervuex

由于这些类型声明是在 NPM 上发布的,并且最新的 TypeScript 知道如何在 NPM 包中解析类型声明,这意味着通过 NPM 安装时,您不需要任何额外的工具就可以使用 TypeScript 与 Vue 协同工作。

// tsconfig.json
{
"compilerOptions": {
// this aligns with Vue's browser support
"target": "es5",
// this enables stricter inference for data properties on `this`
"strict": true,
// if using webpack 2+ or rollup, to leverage tree shaking:
"module": "es2015",
"moduleResolution": "node"
}
}

请注意,您必须包含 strict: true(或者至少包含 noImplicitThis: true,它是 strict 标志的一部分)以利用组件方法中 this 的类型检查,否则它始终被视为 any 类型。

有关更多详细信息,请参阅 TypeScript 编译器选项文档

开发工具

项目创建

Vue CLI 3 可以生成使用 TypeScript 的新项目。要开始

# 1. Install Vue CLI, if it's not already installed
npm install --global @vue/cli

# 2. Create a new project, then choose the "Manually select features" option
vue create my-project-name

编辑器支持

对于使用 TypeScript 开发 Vue 应用程序,我们强烈建议使用 Visual Studio Code,它为 TypeScript 提供了出色的开箱即用支持。如果您使用的是 单文件组件 (SFC),请使用很棒的 Vetur 扩展,它在 SFC 中提供 TypeScript 推断以及许多其他很棒的功能。

WebStorm 也为 TypeScript 和 Vue 提供开箱即用支持。

基本用法

要让 TypeScript 在 Vue 组件选项中正确推断类型,您需要使用 Vue.componentVue.extend 定义组件

import Vue from 'vue'

const Component = Vue.extend({
// type inference enabled
})

const Component = {
// this will NOT have type inference,
// because TypeScript can't tell this is options for a Vue component.
}

类风格 Vue 组件

如果您在声明组件时更喜欢基于类的 API,您可以使用官方维护的 vue-class-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)
}
}

增强类型以用于插件

插件可能会添加到 Vue 的全局/实例属性和组件选项中。在这些情况下,需要类型声明才能使插件在 TypeScript 中编译。幸运的是,TypeScript 有一个增强现有类型的功能,称为 模块增强

例如,要声明一个类型为 string 的实例属性 $myProperty

// 1. Make sure to import 'vue' before declaring augmented types
import Vue from 'vue'

// 2. Specify a file with the types you want to augment
// Vue has the constructor type in types/vue.d.ts
declare module 'vue/types/vue' {
// 3. Declare augmentation for Vue
interface Vue {
$myProperty: string
}
}

在将上述代码作为声明文件(如 my-property.d.ts)包含在您的项目中之后,您可以在 Vue 实例上使用 $myProperty

var vm = new Vue()
console.log(vm.$myProperty) // This should compile successfully

您还可以声明其他全局属性和组件选项

import Vue from 'vue'

declare module 'vue/types/vue' {
// Global properties can be declared
// on the `VueConstructor` interface
interface VueConstructor {
$myGlobal: string
}
}

// ComponentOptions is declared in types/options.d.ts
declare module 'vue/types/options' {
interface ComponentOptions<V extends Vue> {
myOption?: string
}
}

上述声明允许编译以下代码

// Global property
console.log(Vue.$myGlobal)

// Additional component option
var vm = new Vue({
myOption: 'Hello'
})

注释返回类型

由于 Vue 的声明文件的循环性质,TypeScript 可能难以推断某些方法的类型。出于这个原因,您可能需要在 render 以及 computed 中的方法上注释返回类型。

import Vue, { VNode } from 'vue'

const Component = Vue.extend({
data () {
return {
msg: 'Hello'
}
},
methods: {
// need annotation due to `this` in return type
greet (): string {
return this.msg + ' world'
}
},
computed: {
// need annotation
greeting(): string {
return this.greet() + '!'
}
},
// `createElement` is inferred, but `render` needs return type
render (createElement): VNode {
return createElement('div', this.greeting)
}
})

如果您发现类型推断或成员完成不起作用,注释某些方法可能有助于解决这些问题。使用 --noImplicitAny 选项将有助于找到许多这些未注释的方法。

注释 Props

import Vue, { PropType } from 'vue'

interface ComplexMessage {
title: string,
okMessage: string,
cancelMessage: string
}
const Component = Vue.extend({
props: {
name: String,
success: { type: String },
callback: {
type: Function as PropType<() => void>
},
message: {
type: Object as PropType<ComplexMessage>,
required: true,
validator (message: ComplexMessage) {
return !!message.title;
}
}
}
})

如果您发现验证器没有获得类型推断或成员完成不起作用,使用预期类型注释参数可能有助于解决这些问题。