一 快速开始与脚手架
- 使用官方模板创建 Vue 3 + TypeScript 项目(推荐):
- Vite:
npm create vite@latest my-vue-ts -- --template vue-ts - Vue CLI:
vue create my-vue-ts(交互选择 TypeScript)
- 初始化/检查配置:
- 生成或调整:
npx tsc --init - 编译项目:
npx tsc -p . 或 vue-tsc --noEmit(类型检查)
- 关键说明:
- 当项目根目录存在 tsconfig.json 时,该目录被视为 TypeScript 项目根。
- Vite 项目通常使用 Vue 的 TS 官方预设,已包含合理的默认值;Vue CLI 项目会生成带注释的默认配置,可按需裁剪。
二 推荐配置与字段解读(Vue 3 + Vite)
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "Node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"components/*": ["src/components/*"],
"views/*": ["src/views/*"]
},
"types": ["vite/client", "vue", "node"],
"skipLibCheck": true,
"allowJs": false,
"noEmit": true,
"isolatedModules": true,
"verbatimModuleSyntax": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "src/env.d.ts", "vite.config.ts"],
"exclude": ["node_modules", "dist", "**/*.spec.ts"]
}
- 字段速览与取舍建议:
- extends:继承 @vue/tsconfig 的浏览器/DOM 基线,减少维护成本。
- strict: true:开启全量严格检查,长期收益最大。
- jsx: "preserve":由 Vue 处理模板/JSX;如需自定义工厂名,可改为对象形式。
- moduleResolution: "Node":Node.js 解析策略;若使用 ESM/CJS 互操作,可考虑 node16/nodenext。
- types:包含 vite/client 以获得
import.meta.env、import.meta.glob 等类型提示。 - baseUrl + paths:与打包器(Vite/Webpack)的别名保持一致,避免路径不一致。
- noEmit / isolatedModules / verbatimModuleSyntax:Vite 项目通常仅做类型检查,使用 noEmit;配合 isolatedModules 与 verbatimModuleSyntax 提升跨工具兼容与迁移友好度。
- include/exclude:确保覆盖 .vue 文件与配置入口(如
vite.config.ts),排除 node_modules / dist。
三 声明文件与类型补充
- 全局声明文件 src/env.d.ts(或
src/shims-vue.d.ts):
/// <reference types="vite/client" />
// 声明 Vue 单文件组件类型(配合 <script setup lang="ts">)
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
// 静态资源
declare module '*.png' { const src: string; export default src }
declare module '*.jpg' { const src: string; export default src }
declare module '*.webp' { const src: string; export default src }
declare module '*.svg' { const src: string; export default src }
// 环境变量
interface ImportMetaEnv {
readonly VITE_APP_TITLE: string
readonly VITE_API_BASE_URL: string
// 更多按需补充
}
interface ImportMeta {
readonly env: ImportMetaEnv
}
- 说明:
/// <reference types="vite/client" /> 让 TS 识别 Vite 注入的全局变量。declare module '*.vue' 使 .vue 文件可被模块系统正确导入并具备组件类型推导。
四 SFC 与组合式 API 的类型写法
- 使用 <script setup lang="ts"> 的推荐模式:
<script setup lang="ts">
import { ref, computed } from 'vue'
// Props(推荐使用显式接口)
interface Props {
msg: string
count?: number
}
const props = defineProps<Props>()
// Emits(泛型精确描述事件)
const emit = defineEmits<{
(e: 'update:count', value: number): void
(e: 'submit', payload: { username: string }): void
}>()
// 响应式数据与计算属性
const count = ref(props.count ?? 0)
const double = computed(() => count.value * 2)
const increment = () => {
count.value++
emit('update:count', count.value)
}
</script>
<template>
<div>
<p>{{ msg }} - {{ count }}</p>
<p>Double: {{ double }}</p>
<button @click="increment">+1</button>
<button @click="$emit('submit', { username: 'tom' })">Submit</button>
</div>
</template>
- 关键要点:
- Props/Emits 使用接口或泛型精确描述,IDE 可自动补全并校验事件载荷。
- ref<T> / reactive<T> 显式标注复杂类型,避免隐式
any。 - defineOptions、defineSlots、defineModel 等在需要时按需补充类型信息。
五 常见问题与最佳实践
- 路径别名不生效:确保 tsconfig.json 的 paths 与 Vite 的 resolve.alias 完全一致(包括 baseUrl)。
- 第三方库无类型或报错:优先安装
@types/xxx;无类型时可用 // @ts-ignore 临时规避或补充 .d.ts。 - 编译速度慢:
- 开启 skipLibCheck: true;
- 收窄 include 范围,避免包含测试/生成文件;
- 大型项目可结合项目引用(Project References)拆分代码。
- 仅类型检查:设置 noEmit: true,在 CI 中运行
vue-tsc --noEmit 统一校验。 - 严格模式下的常见坑:
- Props/Emits 类型不完整会导致运行期隐患与提示缺失,务必显式声明;
- ref 可能为 null:访问前先判空或使用可选链;
- 大小写文件名 跨平台问题:启用 forceConsistentCasingInFileNames: true。