2024-05-01|閱讀時間 ‧ 約 23 分鐘

Vue 3 script setup defineProps 的坑

問題

最近筆者在學習如何於 Vue 專案中使用 Apollo Graphql Client 從 API 獲取資料,由於資料來自 GraphqlZero ,結構較為複雜,筆者便跟著網路教學使用 codegen 工具自動化產生 TypeScript 型別定義。在某個元件中,需要使用 defineProps 這個 API 來傳遞 Post 這筆資料,於是很天真的在 <script setup> 裡面寫:


原以為可以輕易地使用自訂型別...

結果意想不到的事情發生了,竟然在 runtime 發生 ReferenceError 錯誤

What? TypeScript 跑到 runtime 了??


推測原因

針對此問題,猜測原因有兩種可能:

  • 這是 Apollo Client 的坑
  • 這是 import type 的坑
  • 這是 Vue 在 TypeScript 的坑


於是我看了一下範例程式碼,發現自己在 Apollo Client 使用上應該是沒有錯誤。找了一下網路文章,也都沒有提到 Apollo Client 會造成 TypeScript 在 runtime 報錯的案例。


那麼,會不會是 import Post 這個型別時出了什麼差錯?於是我查了一下 TypeScript 關於 import type 寫法的說明:

裡面有提到可以在 tsconfig 裡面 用 "importsNotUsedAsValues" 這個屬性,來避免 type 被當成 JavaScript 變數處理。我修改了一下 tsconfig.app.json 檔案:

vite 和 Vue 官方把 tsconfig 拆成好幾份,足見 TS 有多麻煩


解決方式

以上嘗試都沒有改變結果,後來我逐行檢視,發現問題可能出在 defineProps 定義 post 的型別時:

這裏是使用自訂義的型別,而非 Vue 官方提供的 String、Array、Object 等型別定義,問題是出在這嗎?


在 Vue 文件的 <script setup> 一節中提到,雖然有支援自訂型別,但太過複雜的型別定義, Vue 可能還是會無法辨識,把它當作一般的 runtime 變數。讓我們來看看 Post 這個型別的內容吧。

如此複雜的型別定義


於是,我想到既然 Post 是一個物件,若使用 Object 配合 TypeScript 的 as 做型別斷言,或許可以成功?

object as Post...總算解決型別定義問題


之後終於讓 TypeScript 把 Post 當成型別定義,不會在 runtime 報錯了。這個坑還真是深,且筆者還注意到,若在 defineProps 使用 Post [] ,不會有任何錯誤,可能 TypeScript 會讓它 fallback 為一般的陣列吧⋯⋯

分享至
成為作者繼續創作的動力吧!
從 Google News 追蹤更多 vocus 的最新精選內容從 Google News 追蹤更多 vocus 的最新精選內容

廖偉帆的沙龍 的其他內容

發表回應

成為會員 後即可發表留言
© 2024 vocus All rights reserved.