TypeScript 与 Vue.js
1. Vue.js 与 TypeScript 的集成背景
Vue.js 从 2.x 版本开始逐步增强对 TypeScript 的支持,到 Vue 3.x 时已实现原生 TypeScript 开发体验。TypeScript 为 Vue 提供了:
- 组件 Props/Emits 的静态类型检查
- 模板逻辑的间接类型安全(通过 Volar 插件)
- 更好的 Composition API 类型推断
2. 项目初始化配置
通过 Vue CLI 创建项目
vue create my-project --default
vue add typescript
或使用 Vite 模板
npm create vite@latest my-vue-app --template vue-ts
3. 核心功能类型化
组件 Props 类型定义
<script setup lang="ts">
interface Props {
title: string
count?: number
isActive: boolean
}
const props = defineProps<Props>()
</script>
组件 Emits 类型定义
const emit = defineEmits<{
(e: 'update', payload: string): void
(e: 'delete'): void
}>()
Ref 与 Reactive 类型
import { ref, reactive } from 'vue'
// 自动推断为 Ref<number>
const count = ref(0)
// 显式泛型
const user = ref<{ name: string }>({ name: 'Alice' })
// Reactive 类型
interface State {
loading: boolean
data: string[]
}
const state = reactive<State>({
loading: false,
data: []
})
4. Composition API 类型实践
类型化自定义 Hook
import { ref, onMounted } from 'vue'
export function useFetch<T>(url: string) {
const data = ref<T | null>(null)
const error = ref<Error | null>(null)
onMounted(async () => {
try {
const response = await fetch(url)
data.value = await response.json()
} catch (err) {
error.value = err as Error
}
})
return { data, error }
}
类型化 Store (Pinia 示例)
import { defineStore } from 'pinia'
interface User {
id: number
name: string
}
export const useUserStore = defineStore('user', {
state: () => ({
users: [] as User[],
currentUser: null as User | null
}),
actions: {
async fetchUsers() {
const res = await fetch('/api/users')
this.users = await res.json()
}
}
})
5. 模板中的类型支持
通过 Volar 插件实现:
- 模板表达式类型检查
- 组件 Prop 自动补全
- 事件处理器参数类型提示
6. 常见问题解决方案
第三方组件类型扩展
// 扩展全局组件类型
declare module 'vue' {
export interface GlobalComponents {
RouterLink: typeof import('vue-router')['RouterLink']
ElButton: typeof import('element-plus')['ElButton']
}
}
解决 Vue 文件导入报错
在 env.d.ts 中添加:
declare module '*.vue' {
import { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
7. 最佳实践建议
- 优先使用
<script setup>语法 - 为复杂数据接口定义独立类型文件
- 开启
strict: true编译选项 - 使用 Volar 替代 Vetur 获得完整 TS 支持
- 定期更新 @vue/compiler-sfc 和 typescript 依赖
版本注意:本文示例基于 Vue 3.3+ 和 TypeScript 5.0+,部分语法在旧版本可能需要调整。
