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
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
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
如何在 Vite 專案中安裝和設置 TypeScript 及路徑別名的步驟,包括安裝必要的依賴、配置 vite.config.js、tsconfig.json 的設置,及如何創建類型聲明文件來正確識別 .vue 文件。
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
平常我們在 html 上常看到的例如 v-for、v-model 等等... 也是VUE已經幫我們定義好的指令,而這次我們可以依這自己的需求來建立。 此功能屬於較進階的功能,因此實戰中會比較少見,市面上還是有不少完善的套件能達到同樣效果,建議可以先往這方面察找
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
2023 Vue直播班筆記 - 動態路由Props,接續之前的一般動態路由。分為 "寫死" 及 "彈性" 兩種。
一般而言,組件之間的資料傳遞,可以使用 props 來達成,不過一旦層級過多的時候,props 就要逐層向下傳遞,會越來越麻煩且複雜。 而 provide、inject 可以解決這個問題,它可以提供一個「源頭」,子組件們可以藉由同一個源頭取得對應的資料,且沒有層級分別,都可以取得,就不用逐層傳遞資
Thumbnail
在 Vue 中,組件是構建應用程式的基本單位,而 props 是組件間傳遞資料的主要方式之一,本文將介紹 Vue 中的 props,並通過實際範例展示如何使用 props 實現組件間的資料傳遞。
Thumbnail
在 Vue 中,methods和computed是用於定義元件的行為和計算屬性。本文將介紹methods和computed屬性的使用方法和區別,並通過實際範例來幫助你理解。
Thumbnail
Vue 提供了兩種不同的 API 來建立和管理組件:Option API 和 Composition API。本文將介紹這兩種 API 的特點和差異,並透過實際範例來理解它們的使用方式。
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
如何在 Vite 專案中安裝和設置 TypeScript 及路徑別名的步驟,包括安裝必要的依賴、配置 vite.config.js、tsconfig.json 的設置,及如何創建類型聲明文件來正確識別 .vue 文件。
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
平常我們在 html 上常看到的例如 v-for、v-model 等等... 也是VUE已經幫我們定義好的指令,而這次我們可以依這自己的需求來建立。 此功能屬於較進階的功能,因此實戰中會比較少見,市面上還是有不少完善的套件能達到同樣效果,建議可以先往這方面察找
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
2023 Vue直播班筆記 - 動態路由Props,接續之前的一般動態路由。分為 "寫死" 及 "彈性" 兩種。
一般而言,組件之間的資料傳遞,可以使用 props 來達成,不過一旦層級過多的時候,props 就要逐層向下傳遞,會越來越麻煩且複雜。 而 provide、inject 可以解決這個問題,它可以提供一個「源頭」,子組件們可以藉由同一個源頭取得對應的資料,且沒有層級分別,都可以取得,就不用逐層傳遞資
Thumbnail
在 Vue 中,組件是構建應用程式的基本單位,而 props 是組件間傳遞資料的主要方式之一,本文將介紹 Vue 中的 props,並通過實際範例展示如何使用 props 實現組件間的資料傳遞。
Thumbnail
在 Vue 中,methods和computed是用於定義元件的行為和計算屬性。本文將介紹methods和computed屬性的使用方法和區別,並通過實際範例來幫助你理解。
Thumbnail
Vue 提供了兩種不同的 API 來建立和管理組件:Option API 和 Composition API。本文將介紹這兩種 API 的特點和差異,並透過實際範例來理解它們的使用方式。