Vue 3 script setup defineProps 的坑

更新於 2024/05/06閱讀時間約 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
3會員
5內容數
我是Sail,這裡主要分享一些自己覺得有趣的前端議題。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
廖偉帆的沙龍 的其他內容
為什麼要登出使用者? 安全性:防止未經授權的人,在使用者暫離時使用系統,這在公用或共享電腦的環境中尤其重要。 資料保護:只要使用者處於登入狀態,就會暴露在個人資料被他人操縱或利用的風險中,因此登出閒置使用者對資安也很重要。 如何在 Vue 3 專案中實作此功能?
data-* attributes 是 HTML 內建的屬性,可將網頁的狀態與元素進行綁定。而Tailwind CSS 在 3.2 版更新中推出使用 data-* attributes 自訂樣式的功能,讓樣式設定可以更動態多變。
為什麼要登出使用者? 安全性:防止未經授權的人,在使用者暫離時使用系統,這在公用或共享電腦的環境中尤其重要。 資料保護:只要使用者處於登入狀態,就會暴露在個人資料被他人操縱或利用的風險中,因此登出閒置使用者對資安也很重要。 如何在 Vue 3 專案中實作此功能?
data-* attributes 是 HTML 內建的屬性,可將網頁的狀態與元素進行綁定。而Tailwind CSS 在 3.2 版更新中推出使用 data-* attributes 自訂樣式的功能,讓樣式設定可以更動態多變。
你可能也想看
Google News 追蹤
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
這篇文章記錄了如何在網頁中使用<iframe>或套件vue3-google-map來實現Google Map呈現,並在上面設置圖釘。兩種方法的優缺點也有相關的說明。想要在網頁上加入Google Map及設置圖釘的讀者可以參考這篇文章。
父元件 傳遞方法使用@ <template>    ...    <Login @modalClose="modalClose"/> ... </template> <script setup>     const _modal = ref();     function m
父元件 傳遞變數時須加上冒號 子元件 接收props用法如下 本筆記參考: 1. https://www.netlify.com/blog/understanding-defineprops-and-defineemits-in-vue-3.2 2. https://juejin.cn/post/7
Thumbnail
雖然距離上次Vue直播班課不到一年,但看到這次的課程有Pinia內容,手又不小心刷了魔法小卡(? 意識到自己的成長應該是可以輕鬆地串接API,畢竟去年也已經串到可以去烤串店了XD,就算是重新複習,還是可以從中獲得新的成長,而且發現到老師一年講的比一年還好,今年有很多觀念講得更清楚了! 可惜這次第六週
Thumbnail
專案建好了,那先來講 Vue 的專案架構 詳細內容很多,所以我挑重點講 public index.html public/index.html 是 Vue 頁面的 entry point,進入一個 Vue 頁面會先進 public/index.html,再套用 App.vue,最後才是進入你寫的 .
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
這篇文章記錄了如何在網頁中使用<iframe>或套件vue3-google-map來實現Google Map呈現,並在上面設置圖釘。兩種方法的優缺點也有相關的說明。想要在網頁上加入Google Map及設置圖釘的讀者可以參考這篇文章。
父元件 傳遞方法使用@ <template>    ...    <Login @modalClose="modalClose"/> ... </template> <script setup>     const _modal = ref();     function m
父元件 傳遞變數時須加上冒號 子元件 接收props用法如下 本筆記參考: 1. https://www.netlify.com/blog/understanding-defineprops-and-defineemits-in-vue-3.2 2. https://juejin.cn/post/7
Thumbnail
雖然距離上次Vue直播班課不到一年,但看到這次的課程有Pinia內容,手又不小心刷了魔法小卡(? 意識到自己的成長應該是可以輕鬆地串接API,畢竟去年也已經串到可以去烤串店了XD,就算是重新複習,還是可以從中獲得新的成長,而且發現到老師一年講的比一年還好,今年有很多觀念講得更清楚了! 可惜這次第六週
Thumbnail
專案建好了,那先來講 Vue 的專案架構 詳細內容很多,所以我挑重點講 public index.html public/index.html 是 Vue 頁面的 entry point,進入一個 Vue 頁面會先進 public/index.html,再套用 App.vue,最後才是進入你寫的 .