如果有任何問題或建議,歡迎隨時聯繫我:
各位 Vue 的魔法師們!專案一直以來都由 JavaScript 這位自由奔放、充滿創意的藝術家主導。他隨性、靈活,能快速揮灑出各種功能。但有時候...他實在太自由了,偶爾會把紅色顏料當成藍色(傳錯了變數型別),直到畫作展出(程式碼運行)時,我們才驚覺:「天啊!怎麼會這樣!」
今天,我們要為我們的團隊請來一位紀律嚴明的「架構師」—— TypeScript!
很多人一聽到要在現有專案引入 TypeScript,腦中就浮現「紅色錯誤海嘯」的恐怖畫面,感覺像是打開了潘朵拉的盒子。別怕!這很正常。今天的任務,就是給你一份「無痛升級作戰手冊」,一步步帶你從 JavaScript 自由派,平穩過渡到 TypeScript 紀律部隊,為你的程式碼加上「品質保證」!
在開始動手前,我們先來點心理建設。為什麼要放棄自由,擁抱紀律?
錯誤的「先知」:TS 就像一個有預知能力的夥伴,在你的程式碼還沒跑起來之前,它就會拍拍你的肩膀說:「嘿,老兄,你這裡不小心把數字傳給一個需要字串的函式了,趕快改一下。」這能消滅掉無數個可能在半夜把你叫醒的 Bug。
會讀心術的 IDE:當你用上 TS,你的 VS Code 就像吃了大還丹,功力大增。它能精準地提示你物件有哪些屬性、函式該傳什麼參數,自動補全功能變得無比絲滑,寫起程式碼來行雲流水。
團隊合作的「共同語言」:TS 的型別定義就是一份活的、不會說謊的「技術文件」。隊友一看就知道你的組件需要什麼 props,你的函式回傳什麼資料,大大減少了溝通成本和誤解。
假設你手上有一個用 Vite 建立的純 JS 的 Vue 3 專案。別擔心,我們一步步來。
首先,我們需要安裝 TypeScript 編譯器和一個專門「翻譯」Vue 檔案給 TS 聽的工具 vue-tsc。
# 使用 npm
npm install -D typescript vue-tsc
# 或使用 yarn
yarn add -D typescript vue-tsc
typescript: TS 的核心編譯器,我們的大腦。vue-tsc: 專門用來檢查 .vue 檔案的工具,是我們的「Vue 專家顧問」。tsconfig.json)在專案根目錄下建立一個 tsconfig.json 檔案。這是 TS 的「作戰計畫書」,告訴它該如何工作。
先別急著追求完美! 我們的首要目標是「讓專案先能跑起來」,而不是立刻解決所有問題。所以,我們先用一個比較寬鬆的「急救設定」:
// tsconfig.json
{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "node",
    "strict": false, // 先關掉嚴格模式,給自己一點喘息空間!
    "noImplicitAny": false, // 允許隱性的 any 型別,暫時忽略一些警告
    "skipLibCheck": true, // 跳過對 node_modules 裡宣告檔案的檢查,加速編譯
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "sourceMap": true,
    "baseUrl": ".",
    "types": ["vite/client"], // 如果你用 Vite
    "paths": {
      "@/*": ["src/*"] // 讓 TS 看得懂 @/ 這種路徑別名
    },
    "lib": ["ESNext", "DOM", "DOM.Iterable"]
  },
  // 告訴 TS 該檢查哪些檔案
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  // 如果你的專案有 tsconfig.node.json,就加上這個引用
  "references": [{ "path": "./tsconfig.node.json" }]
}
重點:
strict: false和noImplicitAny: false是我們暫時的「和平協議」。這能讓你在遷移初期,不會被成千上萬的錯誤淹沒。我們的策略是:先求有,再求好。
好了,深呼吸。現在,把你的 main.js 改名為 main.ts,然後隨便找一個 .vue 檔案,把 <script setup> 改成 <script setup lang="ts">。
然後執行 npm run dev... 砰!你的終端機可能就「炸」了,一片紅。別慌,這是正常的!我們來一個個拆解。
Cannot find module './components/MyButton.vue'. ts(2307)這是最常見的錯誤。因為 TS 天生不認識 .vue 檔案是什麼碗糕。你需要手動「教」它。
解決方案:在你的 src 資料夾下,建立一個 env.d.ts 或 vue-shims.d.ts 檔案,貼上以下程式碼:
// src/env.d.ts
declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
}
這段程式碼等於是告訴 TS:「嘿,以後看到 .vue 結尾的檔案,你就把它當成一個 Vue 組件來處理,別再大驚小怪了!」
Could not find a declaration file for module 'some-library'.當你引入一個純 JS 的第三方函式庫時,TS 會抱怨說:「我不知道這個函式庫的『說明書』(型別定義檔)在哪。」
解決方案:
npm 查一下,通常這個函式庫的型別定義會以 @types/ 開頭。例如,如果你用了 lodash,就執行 npm install -D @types/lodash。env.d.ts,在裡面加一行:
declare module 'some-library';
some-library 這個東西,相信我就對了。」這能暫時解決問題,讓專案跑起來。當你的專案終於能再次成功運行時,恭喜你,最難的一步已經過去了!
現在,不要貪心。一次只專心修改一個組件。
.vue 檔案,加上 lang="ts"。ref, reactive 加上型別。當你對 TS 越來越有信心時,就可以回到 tsconfig.json,把 noImplicitAny 改回 true,最終目標是開啟 strict: true,享受最嚴格的保護!
Vue 3 為了讓我們能愉快地使用 TS,提供了一些專用武器:
ref<T>(): 你可以明確告訴 ref 它要保管什麼型別的資料,例如 const name = ref<string>('Alice');。defineProps<T>(): 這是 Composition API 的一大亮點!你可以用 interface 或 type 來定義 props 的型別,超級清晰!defineEmits<T>(): 同樣地,你也可以為 emits 定義型別,告訴大家這個組件會發出哪些事件。這些我們在接下來的章節會詳細介紹,它們會讓你的 Vue + TS 開發體驗更上一層樓!
lang="ts" 並修復所有型別錯誤。今天我們進行了一場「專案升級作戰」。記住,從 JS 遷移到 TS 的關鍵在於循序漸進。不要指望一蹴可幾。先用寬鬆的設定讓專案「活下來」,然後再逐步、分批地收緊規則,清理錯誤。這個過程就像是整理一個雜亂的房間,一次整理一個角落,最終你會得到一個乾淨、整潔、令人安心的空間。
本日關鍵字回顧
tsconfig.json: TS 的設定檔,我們的作戰計畫書。vue-tsc: 專門檢查 Vue 檔案的 TS 工具。declare module: 用來「教」TS 認識它不認識的模組,如 .vue 檔案。strict: true: 我們追求的終極「嚴格模式」。恭喜你完成了這次艱鉅但回報豐厚的升級!明天,我們將深入學習如何在 Vue 中使用 TS 的超強武器:型別化的 Props 與 Emits!