Vue 3 script setup defineProps 的坑

更新於 發佈於 閱讀時間約 1 分鐘

問題

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


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

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

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

What? TypeScript 跑到 runtime 了??

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 有多麻煩

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


解決方式

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

raw-image

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

raw-image


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

如此複雜的型別定義

如此複雜的型別定義


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

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

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


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

留言
avatar-img
留言分享你的想法!
avatar-img
廖偉帆的沙龍
3會員
5內容數
我是Sail,這裡主要分享一些自己覺得有趣的前端議題。
廖偉帆的沙龍的其他內容
2024/05/30
在進行Electron 專案時,後端夥伴選擇將 sqlite 資料庫跟專案檔打包成一個執行檔。在開發過程中,前端的操作經常會更動到 db的資料,此時 Git 就會追蹤到 db 的變化,因此前端在推送檔案到遠端 repo 前,會需要將其移出 Git 追蹤範圍,該怎麼做?
Thumbnail
2024/05/30
在進行Electron 專案時,後端夥伴選擇將 sqlite 資料庫跟專案檔打包成一個執行檔。在開發過程中,前端的操作經常會更動到 db的資料,此時 Git 就會追蹤到 db 的變化,因此前端在推送檔案到遠端 repo 前,會需要將其移出 Git 追蹤範圍,該怎麼做?
Thumbnail
2024/05/13
在串接第三方 API時,需要定期刷新 token,那有沒有辦法針對 request 和 response 做配置,在 token 過期時先做刷新、再做請求呢?本文要介紹利用 axios 套件提供的攔截器刷新 token 的作法。
Thumbnail
2024/05/13
在串接第三方 API時,需要定期刷新 token,那有沒有辦法針對 request 和 response 做配置,在 token 過期時先做刷新、再做請求呢?本文要介紹利用 axios 套件提供的攔截器刷新 token 的作法。
Thumbnail
2024/04/28
為什麼要登出使用者? 安全性:防止未經授權的人,在使用者暫離時使用系統,這在公用或共享電腦的環境中尤其重要。 資料保護:只要使用者處於登入狀態,就會暴露在個人資料被他人操縱或利用的風險中,因此登出閒置使用者對資安也很重要。 如何在 Vue 3 專案中實作此功能?
Thumbnail
2024/04/28
為什麼要登出使用者? 安全性:防止未經授權的人,在使用者暫離時使用系統,這在公用或共享電腦的環境中尤其重要。 資料保護:只要使用者處於登入狀態,就會暴露在個人資料被他人操縱或利用的風險中,因此登出閒置使用者對資安也很重要。 如何在 Vue 3 專案中實作此功能?
Thumbnail
看更多
你可能也想看
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
如何在 Vite 專案中安裝和設置 TypeScript 及路徑別名的步驟,包括安裝必要的依賴、配置 vite.config.js、tsconfig.json 的設置,及如何創建類型聲明文件來正確識別 .vue 文件。
Thumbnail
如何在 Vite 專案中安裝和設置 TypeScript 及路徑別名的步驟,包括安裝必要的依賴、配置 vite.config.js、tsconfig.json 的設置,及如何創建類型聲明文件來正確識別 .vue 文件。
Thumbnail
先前提到 Quasar 的 Dialog Plugin 很好用,再讓我補充一個用法。
Thumbnail
先前提到 Quasar 的 Dialog Plugin 很好用,再讓我補充一個用法。
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
本章節旨在介紹TypeScript的基本語法,包括一般結構、程式進入點、註解以及變數的定義和賦值。這些知識將幫助讀者瞭解TypeScript的基本架構,並且可以開始使用TypeScript進行開發。
Thumbnail
本章節旨在介紹TypeScript的基本語法,包括一般結構、程式進入點、註解以及變數的定義和賦值。這些知識將幫助讀者瞭解TypeScript的基本架構,並且可以開始使用TypeScript進行開發。
Thumbnail
平常我們在 html 上常看到的例如 v-for、v-model 等等... 也是VUE已經幫我們定義好的指令,而這次我們可以依這自己的需求來建立。 此功能屬於較進階的功能,因此實戰中會比較少見,市面上還是有不少完善的套件能達到同樣效果,建議可以先往這方面察找
Thumbnail
平常我們在 html 上常看到的例如 v-for、v-model 等等... 也是VUE已經幫我們定義好的指令,而這次我們可以依這自己的需求來建立。 此功能屬於較進階的功能,因此實戰中會比較少見,市面上還是有不少完善的套件能達到同樣效果,建議可以先往這方面察找
Thumbnail
VUE為單向資料流的框架,在鄰近層級之間我們可以依靠 props 由父層向子層來傳遞需要的資料,然而遇到跨層級的架構時,雖然也是可以一層層傳進去,只是這會造成多餘的處理及凌亂的程式碼,因此才有了 "provide" 來解決我們跨層級的需求。 層級展示圖
Thumbnail
VUE為單向資料流的框架,在鄰近層級之間我們可以依靠 props 由父層向子層來傳遞需要的資料,然而遇到跨層級的架構時,雖然也是可以一層層傳進去,只是這會造成多餘的處理及凌亂的程式碼,因此才有了 "provide" 來解決我們跨層級的需求。 層級展示圖
Thumbnail
Vue.js是一種基於MVVM的前端JavaScript框架,類似的框架有React、Angular等。 架設環境 安裝Visual Studio Code(https://code.visualstudio.com/) 安裝Node.js(https://nodejs.org/en/
Thumbnail
Vue.js是一種基於MVVM的前端JavaScript框架,類似的框架有React、Angular等。 架設環境 安裝Visual Studio Code(https://code.visualstudio.com/) 安裝Node.js(https://nodejs.org/en/
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News