最近筆者在學習如何於 Vue 專案中使用 Apollo Graphql Client 從 API 獲取資料,由於資料來自 GraphqlZero ,結構較為複雜,筆者便跟著網路教學使用 codegen 工具自動化產生 TypeScript 型別定義。在某個元件中,需要使用 defineProps
這個 API 來傳遞 Post 這筆資料,於是很天真的在 <script setup>
裡面寫:
結果意想不到的事情發生了,竟然在 runtime 發生 ReferenceError 錯誤
針對此問題,猜測原因有兩種可能:
於是我看了一下範例程式碼,發現自己在 Apollo Client 使用上應該是沒有錯誤。找了一下網路文章,也都沒有提到 Apollo Client 會造成 TypeScript 在 runtime 報錯的案例。
那麼,會不會是 import Post
這個型別時出了什麼差錯?於是我查了一下 TypeScript 關於 import type 寫法的說明:
裡面有提到可以在 tsconfig 裡面 用 "importsNotUsedAsValues"
這個屬性,來避免 type 被當成 JavaScript 變數處理。我修改了一下 tsconfig.app.json 檔案:
以上嘗試都沒有改變結果,後來我逐行檢視,發現問題可能出在 defineProps 定義 post 的型別時:
這裏是使用自訂義的型別,而非 Vue 官方提供的 String、Array、Object 等型別定義,問題是出在這嗎?
在 Vue 文件的 <script setup>
一節中提到,雖然有支援自訂型別,但太過複雜的型別定義, Vue 可能還是會無法辨識,把它當作一般的 runtime 變數。讓我們來看看 Post 這個型別的內容吧。
於是,我想到既然 Post
是一個物件,若使用 Object
配合 TypeScript 的 as
做型別斷言,或許可以成功?
之後終於讓 TypeScript 把 Post 當成型別定義,不會在 runtime 報錯了。這個坑還真是深,且筆者還注意到,若在 defineProps
使用 Post []
,不會有任何錯誤,可能 TypeScript 會讓它 fallback 為一般的陣列吧⋯⋯