
嘿嘿,大家寫 TypeScript 是不是也常常踩雷呢?
其實 TypeScript 超好用,但那種突然冒出來的錯誤訊息,真的會讓人瞬間卡住啊!
不用怕,這篇就是你的救星!
我會帶你一起來破解那些搞得人頭昏腦脹的 TypeScript 錯誤,幫你解鎖各種「我哪有寫錯!」的迷之瞬間!
不管是神出鬼沒的 any 類型、還是奇怪的 never 錯誤,通通包在我身上!
就讓我們輕鬆搞定這些煩人的小bug,讓你的程式碼從此不再鬧脾氣!一起變更強吧~
type Talk = {
  title: string,
  abstract: string,
  speaker: string
}
type TechEventBase = {
  title: string,
  description: string
  date: Date,
  capacity: number,
  rsvp: number,
  kind: EventKind
}
type Conference = TechEventBase & {
  location: string,
  price: number,
  talks: Talk[],
  kind: 'conference'
}
type Meetup = TechEventBase & {
  location: string,
  price: string,
  talks: Talk[],
  kind: 'meetup'
}
type Webinar = TechEventBase & {
  url: string,
  price?: number,
  talks: Talk,
  kind: 'webinar'
}
type TechEvent = Webinar | Conference | Meetup;
type EventKind =  'conference' | 'meetup' | 'webinar'
type UserEvents = {
  watching: TechEvent[],
  rsvp: TechEvent[],
  attended: TechEvent[],
  signedout: TechEvent[],
}
type UserEventCategory = 
  'watching' | 'rsvp' | 'attended' | 'signedoff'
function filterUserEvent(
  userEventList: UserEvents,
  category: UserEventCategory,
  filterKind?: EventKind
) {
  const filteredList = userEventList[category]
  if (filterKind) {
    return filteredList.filter(event =>
      event.kind === filterKind)
  }
  return filteredList
}
function getEventTeaser(event: TechEvent) {
  switch(event.kind) {
    case 'conference':
      return `${event.title} (Conference), ` + 
        `priced at ${event.price} USD`
    case 'meetup':
      return `${event.title} (Meetup), ` + 
        `hosted at ${event.location}`
    case 'webinar':
      return `${event.title} (Webinar), ` +
        `available online at ${event.url}`
    case 'hackathon':
      return `${event.title} (Hackathon)`
    default:
      throw new Error('Not sure what to do with that!')
  }
}
在這段程式碼中,我們遇到了一些常見的 TypeScript 錯誤。
這些錯誤若不修正,將影響程式的正常運行。
接下來,我將逐步解析每個錯誤的原因、如何解決,並提供修正後的程式碼。
UserEventCategory 類型的表達式無法用於索引類型 UserEvents,因此元素隱式具有 any 類型。這個錯誤的根本原因是 TypeScript 無法確認 UserEventCategory 中的 category 參數可以安全地索引 UserEvents。這是因為 UserEventCategory 包含了 'signedoff',而 UserEvents 對應的鍵名其實是 'signedout'。
解決方法:
UserEventCategory 的 'signedoff' 修改為 'signedout',確保名稱對應一致。修正後的程式碼:
type UserEventCategory = 'watching' | 'rsvp' | 'attended' | 'signedout';
event 隱式具有 any 類型。在 filterUserEvent 函式中,使用 filter 方法時,TypeScript 無法自動推斷 event 參數的類型,因此會預設為 any,這樣做容易引發類型安全問題。
解決方法:
filter 方法中的 event 參數類型為 TechEvent。修正後的程式碼:
function filterUserEvent(
  userEventList: UserEvents,
  category: UserEventCategory,
  filterKind?: EventKind
) {
  const filteredList = userEventList[category];
  if (filterKind) {
    return filteredList.filter((event: TechEvent) => 
      event.kind === filterKind);
  }
  return filteredList;
}
"hackathon" 無法與 "conference" | "meetup" | "webinar" 類型進行比較。這個錯誤出現在 getEventTeaser 函式中的 switch 語句中,因為 'hackathon' 並不在 EventKind 類型定義中,且也未被任何 TechEvent 使用,因此類型不匹配。
解決方法:
switch 語句中的 'hackathon',確保處理的類型符合 EventKind 的定義。修正後的程式碼:
function getEventTeaser(event: TechEvent) {
  switch(event.kind) {
    case 'conference':
      return `${event.title} (Conference), ` + 
        `priced at ${event.price} USD`;
    case 'meetup':
      return `${event.title} (Meetup), ` + 
        `hosted at ${event.location}`;
    case 'webinar':
      return `${event.title} (Webinar), ` +
        `available online at ${event.url}`;
    default:
      throw new Error('Not sure what to do with that!');
  }
}
'title' 不存在於 never 類型上。這個錯誤是因為 TypeScript 無法確定 getEventTeaser 中 event 的正確類型,推斷結果為 never 類型。這通常是因為處理了不應該存在的類型(如 'hackathon'),導致 TypeScript 無法理解 event 的結構。
解決方法:
switch 案例匹配正確定義的類型,這樣就不會出現 never 類型錯誤。索引簽名不匹配:
明確定義類型:
any,這樣能讓 TypeScript 的類型檢查機制發揮作用,保證程式的安全性和可讀性。Switch 案例的類型匹配:
switch 語句應只處理定義內的有效類型。如果加入未定義的類型,會導致 TypeScript 無法正確推斷類型,引發 never 錯誤。正確處理類型:
透過這些修正,程式碼會更符合 TypeScript 的嚴格類型系統,不僅提升開發體驗,還能在開發過程中及早發現問題,避免潛在的錯誤。
好啦,今天的 TypeScript 除錯小冒險就到這邊啦
希望看完之後,大家在面對那些奇奇怪怪的錯誤訊息時,不再感到手足無措。
別忘了,程式開發就是這樣,一步步踩坑、一步步成長,這才是進步的關鍵!
下次遇到 bug 就別怕了,拿出你的自信和技巧,把它當作練等升級的好機會!
Coding 這條路上,我們都在一起學習、一起變強,未來也會越來越厲害~
加油,寫出屬於自己的神級程式吧!💪🚀✨