【Vue】TypeScript与Vue3集成
个人主页:Guiat
归属专栏:Vue
文章目录
- 1. 前言
- 2. 环境准备与基础搭建
- 2.1. 安装 Node.js 与 npm/yarn/pnpm
- 2.2. 创建 Vue3 + TypeScript 项目
- 2.2.1. 使用 Vue CLI
- 2.2.2. 使用 Vite(推荐)
- 2.2.3. 目录结构简述
- 3. Vue3 + TS 基础语法整合
- 3.1. Composition API 集成 TypeScript
- 3.1.1. 基础组件写法
- 3.1.2. Props 与类型约束
- 3.1.3. Emits 事件类型声明
- 3.2. Options API 简要对比
- 4. TypeScript 类型系统与 Vue3 深度融合
- 4.1. 基本类型断言
- 4.2. 泛型加强
- 4.2.1. `ref<T>`
- 4.2.2. `defineProps<T>`, `defineEmits<T>`
- 4.3. 类型辅助工具活用
- 4.3.1. 类型导出 reuse
- 4.3.2. 联合类型、类型推断
- 5. 组件开发全流程:TypeScript 全类型实践
- 5.1. 父子组件 Props + Emits 综合举例
- 5.1.1. 子组件定义
- 5.1.2. 父组件使用
- 5.2. 插槽与类型声明
- 6. 全局属性与模块类型扩展
- 6.1. app.config.globalProperties 类型扩展
- 6.1.1. 类型声明
- 6.1.2. 组件中类型无误调用
- 7. TS 下的常用第三方库引入与类型声明
- 7.1. 以 Axios 为例
- 7.1.1. 安装与引入
- 7.1.2. 类型化 Api 封装
- 7.1.3. 组件调用
- 7.2. 第三方库缺失类型声明问题
- 8. Vue Router & Pinia 全类型支持
- 8.1. 路由类型保驾护航
- 8.1.1. 安装
- 8.1.2. 路由元数据类型增强
- 8.1.3. 全局类型合并扩展(如 TS 智能感知 meta)
- 8.2. Pinia 全类型示例
- 8.2.1. 安装
- 8.2.2. 定义类型安全 store
- 8.2.3. 组件类型安全调用
- 9. 综合场景实践
- 9.1. 类型安全的表单组件
- 9.1.1. 定义表单字段类型
- 9.1.2. 组件使用类型安全表单 state
- 9.1.3. 集成第三方表单库(如 vee-validate)
- 10. 典型架构场景图表分析
- 10.1. 项目类型传递/共享关系图
- 10.2. 业务拆包与类型定义分层
- 11. TypeScript + Vue3 最佳实践要点
- 12. 总结
正文
1. 前言
TypeScript 作为现代前端开发的主流静态类型语言,极大增强了代码的规范性和可维护性。Vue3 作为前端主流框架,官方也对 TypeScript 提供了全力支持。TypeScript 与 Vue3 的集成不仅能够提升开发效率,还能显著减少运行时错误,是现代企业项目的首选。
本文将以多级阿拉伯数字标题的方式,系统讲解 TypeScript 与 Vue3 集成的各个方面,涵盖环境搭建、基础语法整合、类型声明、组件开发、全局属性、第三方库引入、常见场景实践以及最佳实践建议。同时,配以典型代码示例和关键结构图表,助力理解。
**注意:**本文不会涉及 Vue3 的响应式原理与数据绑定相关内容,专注于 TypeScript 实战应用。
2. 环境准备与基础搭建
2.1. 安装 Node.js 与 npm/yarn/pnpm
TypeScript 与 Vue3 需借助现代 Node.js 生态环境,推荐使用 LTS 版本。
node -v
npm -v # 或 yarn -v / pnpm -v
2.2. 创建 Vue3 + TypeScript 项目
2.2.1. 使用 Vue CLI
npm install -g @vue/cli
vue create my-vue3-ts-app
# 选择 Vue 3、手动配置特性,勾选 TypeScript
2.2.2. 使用 Vite(推荐)
Vite 是新一代前端构建工具,适用于现代 Vue3 项目。
npm create vite@latest
# 选择 vue + TypeScript 选项
cd my-vue3-ts-app && npm install
2.2.3. 目录结构简述
my-vue3-ts-app/
│
├── src/
│ ├── components/
│ ├── App.vue
│ ├── main.ts
│ └── ...
│
├── tsconfig.json # TypeScript 配置
├── vite.config.ts # 构建工具配置
└── package.json
图表分析:项目结构
3. Vue3 + TS 基础语法整合
Vue3 支持两种主流的组合方式:Options API + TS 和 Composition API + TS。推荐编写业务逻辑时使用 Composition API。
3.1. Composition API 集成 TypeScript
3.1.1. 基础组件写法
src/components/HelloWorld.vue
<script lang="ts" setup>
import { ref } from "vue";const message = ref<string>("Hello TypeScript + Vue3!");
</script><template><div>{{ message }}</div>
</template>
lang="ts"
告诉 Vue 以 TypeScript 解析<script>
setup
语法糖配合 TS 类型推导(ref)
3.1.2. Props 与类型约束
<script lang="ts" setup>
import { defineProps } from 'vue';interface Props {msg: string;count?: number;
}const props = defineProps<Props>();
</script><template><h1>{{ props.msg }}</h1><p v-if="props.count">Count: {{ props.count }}</p>
</template>
3.1.3. Emits 事件类型声明
<script lang="ts" setup>
import { defineEmits } from "vue";const emit = defineEmits<{(event: 'increment', value: number): void
}>();function handleClick() {emit('increment', 1);
}
</script>
3.2. Options API 简要对比
虽然不推荐,新旧项目迁移时经常遇到
<script lang="ts">
import { defineComponent } from 'vue'export default defineComponent({props: {title: String,},methods: {sayHello(msg: string): void {console.log(msg);}}
})
</script>
4. TypeScript 类型系统与 Vue3 深度融合
Vue3 充分利用了 TypeScript 的高级类型。
4.1. 基本类型断言
const name: string = "Alice";
const age: number = 25;
4.2. 泛型加强
如 ref<T>
, defineProps<T>
, defineEmits<T>
, defineExpose<T>
4.2.1. ref<T>
import { ref } from "vue";const user = ref<{name: string, age: number}>({ name: 'Bob', age: 30 });
4.2.2. defineProps<T>
, defineEmits<T>
见前文 3.1.2/3.1.3 示例
4.3. 类型辅助工具活用
代码体验进一步提升:
4.3.1. 类型导出 reuse
types/user.ts
export interface User {id: number;name: string;email: string;
}
组件中使用:
<script lang="ts" setup>
import type { User } from '@/types/user'
const props = defineProps<{ user: User }>();
</script>
4.3.2. 联合类型、类型推断
type Status = 'success' | 'error' | 'loading';const status = ref<Status>('loading');
5. 组件开发全流程:TypeScript 全类型实践
5.1. 父子组件 Props + Emits 综合举例
5.1.1. 子组件定义
src/components/Counter.vue
<script lang="ts" setup>
import { defineProps, defineEmits } from "vue";
interface Props {modelValue: number
}
const props = defineProps<Props>();const emit = defineEmits<{(event: 'update:modelValue', value: number): void
}>();function inc() {emit('update:modelValue', props.modelValue + 1)
}
function dec() {emit('update:modelValue', props.modelValue - 1)
}
</script>
<template><button @click="dec">-</button><span>{{ props.modelValue }}</span><button @click="inc">+</button>
</template>
5.1.2. 父组件使用
<script lang="ts" setup>
import { ref } from 'vue'
import Counter from './components/Counter.vue'const count = ref<number>(0)
</script>
<template><Counter v-model="count"/><p>父组件当前值:{{ count }}</p>
</template>
5.2. 插槽与类型声明
插槽内容可通过 TS 接口声明类型。
<script lang="ts" setup>
interface HeaderSlotProps {title: string
}
defineSlots<{header(props: HeaderSlotProps): void
}>()
</script>
<template><slot name="header" :title="'My Title'"/>
</template>
6. 全局属性与模块类型扩展
6.1. app.config.globalProperties 类型扩展
入口 main.ts
设置全局属性(如 $filters
)
import { createApp } from 'vue'
import App from './App.vue'const app = createApp(App)
app.config.globalProperties.$filters = {capitalize(str: string) {return str.charAt(0).toUpperCase() + str.slice(1);}
}
app.mount('#app')
6.1.1. 类型声明
新建 src/types/vue.d.ts
import { ComponentCustomProperties } from 'vue'declare module '@vue/runtime-core' {interface ComponentCustomProperties {$filters: {capitalize(str: string): string}}
}
6.1.2. 组件中类型无误调用
<script lang="ts" setup>
const str = $filters.capitalize('hello world')
</script>
7. TS 下的常用第三方库引入与类型声明
7.1. 以 Axios 为例
7.1.1. 安装与引入
npm i axios
npm i -D @types/axios
7.1.2. 类型化 Api 封装
import axios from 'axios'export interface ApiResponse<T> {code: number;data: T;message: string;
}
export function getUser(userId: number) {return axios.get<ApiResponse<User>>(`/api/user/${userId}`);
}
7.1.3. 组件调用
<script lang="ts" setup>
import { ref, onMounted } from 'vue'
import { getUser } from '@/api/user'
import type { User } from '@/types/user'const user = ref<User>()
onMounted(async () => {const res = await getUser(123)if(res.data.code === 0) user.value = res.data.data
})
</script>
7.2. 第三方库缺失类型声明问题
如遇第三方库没有 type,需自己声明。
新建 src/types/some-lib.d.ts
:
declare module 'some-lib' {export function hello(name: string): void;
}
8. Vue Router & Pinia 全类型支持
8.1. 路由类型保驾护航
8.1.1. 安装
npm i vue-router
# Vue3 新版已内置类型
8.1.2. 路由元数据类型增强
定义:
import { RouteRecordRaw } from 'vue-router'
interface Meta {requiresAuth?: boolean;title?: string;
}const routes: RouteRecordRaw[] = [{path: '/',name: 'Home',component: () => import('@/views/Home.vue'),meta: {requiresAuth: true,title: '首页'} as Meta}
]
8.1.3. 全局类型合并扩展(如 TS 智能感知 meta)
src/types/router.d.ts
import 'vue-router'
declare module 'vue-router' {interface RouteMeta {requiresAuth?: boolean;title?: string;}
}
8.2. Pinia 全类型示例
8.2.1. 安装
npm i pinia
8.2.2. 定义类型安全 store
src/stores/counter.ts
import { defineStore } from 'pinia'export const useCounterStore = defineStore('counter', {state: () => ({count: 0}),actions: {increment() {this.count++}}
})
8.2.3. 组件类型安全调用
<script lang="ts" setup>
import { useCounterStore } from '@/stores/counter'const counterStore = useCounterStore()
counterStore.increment()
</script>
Pinia 全面使用泛型,无需额外类型声明即可获得全类型推断。
9. 综合场景实践
对真实业务有指导意义的高阶运用:
9.1. 类型安全的表单组件
9.1.1. 定义表单字段类型
interface FormData{username: string,password: string,remember: boolean
}
9.1.2. 组件使用类型安全表单 state
<script lang="ts" setup>
import { reactive } from 'vue'
const form = reactive<FormData>({username: "",password: "",remember: false,
})
</script>
<template><input v-model="form.username" placeholder="用户名"><input v-model="form.password" type="password" placeholder="密码"><input type="checkbox" v-model="form.remember"> 记住我
</template>
9.1.3. 集成第三方表单库(如 vee-validate)
vee-validate 已内置类型支持,可直接配合类型接口。
10. 典型架构场景图表分析
10.1. 项目类型传递/共享关系图
- 统一类型接口放到
types
,Api 层/组件/Pinia 共享 - 保证全链路的数据安全性
10.2. 业务拆包与类型定义分层
11. TypeScript + Vue3 最佳实践要点
- 统一类型声明管理:将类型接口集中管理于
src/types/
文件夹。 - 避免 any:任何时候都应当追求类型精确约束而不是填充 any。
- 泛型更优雅:
ref<T>
、defineProps<T>
、Api 响应等全部泛型化声明。 - 配置 tsconfig.json:合理配置路径映射和检测规则,提升开发体验。
- 配合 IDE 插件和类型检查工具:如 Volar、ESLint/TSLint、Prettier。
- 定期类型升级和重构:利用类型系统减少技术债。
- 善用类型工具:如
Partial<T>
、Pick<T>
、Record<K,V>
等。 - 组件 slot、emit 等交互全类型声明。
12. 总结
TypeScript 与 Vue3 的深度集成为现代前端开发带来革命性的进步。从环境搭建到项目结构优化,从 Props/Emits/Slots 全链路类型声明,到 Pinia、Router、第三方库的类型增强,TS 均可充分发挥威力,极大地提高了代码的可靠性开发幸福感。
前端开发者应尽早拥抱 TypeScript + Vue3,借助强大的类型系统,让团队开发协作更高效、更健壮。
结语
感谢您的阅读!期待您的一键三连!欢迎指正!