TS 筆記 | TypeScript 進階

更新於 2024/11/17閱讀時間約 10 分鐘

型別別名

函式的出現是為了把常用的邏輯包在一起以簡化程式碼增加維護與可讀性。型別的別名也是相同的道理,將常用的型別組合宣告成別名來簡化程式碼。例如:

const addNum = (x: number, y: number): number =>{
return x + y
}

const minusNum = (x: number, y: number): number =>{
return x - y
}

兩個函式都需要為參數和回傳值指定同樣的型別,那這時就可以把相同的內容抽出來做成型別別名:

type NumType = (x: number, y: number)=> number

const addNum: NumType = (x, y) =>{
return x + y
}

const minusNum: NumType = (x, y) =>{
return x - y
}

我們透過 type 來定義別名,並把這個別名作為型別給註記在函式下。



字串字面量型別 (String Literal)

這東西也是使用 type 做定義,所以請把它跟型別別名一起看。

字串字面量型別名字很長,它可以讓我們自己定義一組字串值,而這組字串值可以做為型別註記在變數底下。

像下面例子,當 heading 變數型別註記為 Direction 這個字串字面量型別,那它內部所帶的值就必須滿足 Direction 定義的內容:

type Direction = "north" | "south" | "east" | "west";

let heading: Direction;

heading = "north"; // 正確
heading = "east"; // 正確
heading = "up"; // 錯誤,因為 "up" 不是合法的值

字串字面量型別對以下情況特別有用:

  1. 想限制變數、函式參數或物件屬性只能接受特定字串值時。
  2. 因為可以預期可能的值是哪些,所以提高了程式碼可讀性。



元組 (tuple)

他長得很像陣列,但比陣列嚴苛許多。元組一旦定義下去,它每個 index 該放什麼型別資料以及有多少 index 都必須完全符合定義。舉例來說:

let arr: [string, number, string]

arr = ['hello', 100, 'world']

我在一開始定義了元組,當我後面賦值時就該滿足元組內定義的型別以及數量。

所以說元組在需要保持特定順序和型別的情境下非常有用。比方說,拿來存每個商品的的名稱、價格、購買數量,用這樣一組元組為基礎建立一個購物車函式內容:

// 建立一個元組用來存商品名稱、數量以及價格
type CartItem = [string, number, number]

// 創建購物車
function createShoppingCart(): {
// 回傳內容型別宣告
items: CartItem[],
addItem: (item: CartItem) => void,
calculateTotal: () => number
} {
const items: CartItem[] = [];

// 添加購物車項目
function addItem(item: CartItem): void {
items.push(item);
}

// 計算總價
function calculateTotal(): number {
return items.reduce((total, [_, price, quantity]) => total + price * quantity, 0);
}

return { items, addItem, calculateTotal };
}

// 使用購物車
const shoppingCart = createShoppingCart();

// 添加一些項目到購物車
shoppingCart.addItem(["Laptop", 1000, 2]);
shoppingCart.addItem(["Mouse", 20, 3]);
shoppingCart.addItem(["Keyboard", 50, 1]);

// 計算並輸出總價
const totalPrice = shoppingCart.calculateTotal();
console.log(`Total Price: $${totalPrice}`);



列舉 (enum)

列舉實在是有夠難解釋的,用我的話說就是為抽象的數字賦予有意義的名字,來提高程式碼的可讀性。

舉例來說,我們要表示星期幾,可能會用數字,比如 1 代表星期一,2 代表星期二,以此類推。但是單純用數字寫對於閱讀程式碼的人來說可能不太直觀。

enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat}

從 Sun 開始,這些 "名字" 會依序被賦值 0-7,換句話說,我們正在用有意義的名字來表示一組固定的值。現在,我們就可以使用 Day.Monday 來表示星期一,而不是使用不直觀的數字。



泛型 (Generics)

泛型說白話一點有些把型別當變數用,稍微形象一點形容可以把它想像成一個靈活的容器,允許我們使用不同的型別,而不失去型別安全性。

比如我有一個函式,希望傳入參數是 string 時回傳也是 string,就可以利用泛型:

function myFunc<T>(value: T): T {
return value;
}

let result = myFunc("Hello, TypeScript!");
console.log(result); // "Hello, TypeScript!"

上面發生了什麼事呢?

  1. "Hello, TypeScript!" 作為參數傳入函式。
  2. "Hello, TypeScript!"型別推論為 stringT 因此表示型別為 string

不過其實談到泛型,就會不由自主想到聯合型別和過載 (overloading),同樣都是為了處理多型別代入的情形。實際上在一些情況下,三者達成的功能是一樣的,差別在於語法。至於具體差異大致上是:

  1. 泛型相對靈活與通用。
  2. 聯合型別+型別斷言通常用於處理明確的型別轉換。
  3. 過載則用於提供不同輸入的特定處理邏輯。



[補充] tsconfig.json

前面已經先全局安裝過 TypeScript 了,並且新增了 hello.ts 檔案來練習 TS 語法並透過 tsc hello.js 來編譯 TS 檔案。

但在實務上要開始寫 TS 前會先在一個 tsconfig.json 的檔案中做編譯設定,前面只是為了快速練習 TS 語法所以先跳過這部分。

先在專案下輸入:

tsc --init

就會發現 tsconfig.json 已經出現在專案資料中了。

打開設定檔,先把那些林林總總的註解拿掉,會看到 TS 的預設是這樣:

{
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}
  1. target:指定編譯生成的 JavaScript 的版本。
  2. module:指定了生成模組的格式。CommonJS 是 Node.js 中常見的模組系統。
  3. esModuleInterop:允許 TypeScript 對 CommonJS 模組進行更好的交互操作。
  4. forceConsistentCasingInFileNames:TypeScript 將嚴格檢查文件名的大小寫一致性。
  5. strict:啟用所有的嚴格類型檢查選項
  6. skipLibCheck:跳過對宣告文件 (第三方套件) 的檢查。

基本上只用預設設定 TS 也能動,但你可以客製化讓 TS 更方便,而那一大包註解就是 TS 允許我們自己調整的設定內容,因為很多,就不列舉了。

最後說一下自動編譯。當我在學 TS 每次在那邊 tsc hello.ts 時都在想,SCSS 有自動檢測編譯的功能,TS 有沒有?還真的有,在終端機輸入 tsc --watch 就可以讓 TS 每次在儲存檔案時就自動編譯。而像我一樣 VScode 設定每次變動都自動儲存的人,這就等同無時無刻都在自動編譯了。



參考資料

  1. TypeScript 新手指南
  2. 【Day 12】TypeScript 資料型別 - 元組(Tuple) & 列舉(Enum)
  3. 第二週第一天:型別別名與字串字面量型別
  4. TypeScript | 善用 Enum 提高程式的可讀性 - 基本用法 feat. JavaScript
avatar-img
18會員
37內容數
這個專題用來存放我在學習網頁開發時的心得及知識。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
Jeremy Ho的沙龍 的其他內容
JavaScript Object 基礎操作筆記
JavaScript Array 基本操作筆記
JavaScript event loop / asynchronous.
JavaScript Object 基礎操作筆記
JavaScript Array 基本操作筆記
JavaScript event loop / asynchronous.
你可能也想看
Google News 追蹤
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
ts-rest 可以實現從服務器到客戶端的全型別安全,可以有效降低前後端溝通血流成河的機率。(´,,•ω•,,)
Thumbnail
本文介紹 TypeScript 常遇到的混合型別,以及如何透過五種型別防禦(Type Guard)來解決。涵蓋了使用型別斷言、型別謂詞、in 運算子、typeof 運算子以及 instanceof 運算子這幾種方式。透過本文的學習,能夠更好地運用 TypeScript 進行程式碼開發。
Thumbnail
題目摘要 給定一個整數陣列 `prices`,其中 `prices[i]` 代表第 `i` 天的股票價格。在每一天,你可以決定買入和/或賣出股票。然而,你同一時間只能擁有至多一股股票。你可以在同一天內買入然後立刻賣出股票。找出並返回你可以實現的最大利潤。
Thumbnail
題目摘要 給定一個陣列 prices,其中 prices[i] 代表第 i 天的股票價格。你希望透過在某一天購買一股股票,並在未來的某一天賣出它,以最大化你的利潤。如果無法獲得任何利潤,則返回 0。
Thumbnail
題目摘要: 在這篇文章中,我們將討論如何使用摩爾投票算法找出一個陣列中的「主要元素」。主要元素指的是在陣列中出現次數超過一半的元素,並且我們可以確定它一定存在於陣列中。這個算法的核心思想和應用將在本文中被詳細介紹。 題目知識點: 主要元素的定義和重要性。 摩爾投票算法的工作原理和優點。 先備知識
Thumbnail
重要知識點: 1. TypeScript 全局擴展,使所有陣列都能使用 groupBy 方法。 2. 利用泛型創建彈性函數,提高代碼可重用性。 3. 迭代陣列中的元素,實現遍歷和處理功能。 4. 物件的鍵值對操作,用於建立以函數輸出為鍵的物件。
Thumbnail
這篇文章介紹了如何建立一個時間限制的異步函數,以確保操作在指定時間內完成。 - 知識點包括異步編程、Promise使用、計時器函數和函數引數處理,以及錯誤處理。 - 應用情境包括網頁請求超時控制、前端性能優化和遊戲開發。 - 提高應用程式的可靠性和用戶體驗,確保操作不會花費過長的時間。 - 文章內
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
ts-rest 可以實現從服務器到客戶端的全型別安全,可以有效降低前後端溝通血流成河的機率。(´,,•ω•,,)
Thumbnail
本文介紹 TypeScript 常遇到的混合型別,以及如何透過五種型別防禦(Type Guard)來解決。涵蓋了使用型別斷言、型別謂詞、in 運算子、typeof 運算子以及 instanceof 運算子這幾種方式。透過本文的學習,能夠更好地運用 TypeScript 進行程式碼開發。
Thumbnail
題目摘要 給定一個整數陣列 `prices`,其中 `prices[i]` 代表第 `i` 天的股票價格。在每一天,你可以決定買入和/或賣出股票。然而,你同一時間只能擁有至多一股股票。你可以在同一天內買入然後立刻賣出股票。找出並返回你可以實現的最大利潤。
Thumbnail
題目摘要 給定一個陣列 prices,其中 prices[i] 代表第 i 天的股票價格。你希望透過在某一天購買一股股票,並在未來的某一天賣出它,以最大化你的利潤。如果無法獲得任何利潤,則返回 0。
Thumbnail
題目摘要: 在這篇文章中,我們將討論如何使用摩爾投票算法找出一個陣列中的「主要元素」。主要元素指的是在陣列中出現次數超過一半的元素,並且我們可以確定它一定存在於陣列中。這個算法的核心思想和應用將在本文中被詳細介紹。 題目知識點: 主要元素的定義和重要性。 摩爾投票算法的工作原理和優點。 先備知識
Thumbnail
重要知識點: 1. TypeScript 全局擴展,使所有陣列都能使用 groupBy 方法。 2. 利用泛型創建彈性函數,提高代碼可重用性。 3. 迭代陣列中的元素,實現遍歷和處理功能。 4. 物件的鍵值對操作,用於建立以函數輸出為鍵的物件。
Thumbnail
這篇文章介紹了如何建立一個時間限制的異步函數,以確保操作在指定時間內完成。 - 知識點包括異步編程、Promise使用、計時器函數和函數引數處理,以及錯誤處理。 - 應用情境包括網頁請求超時控制、前端性能優化和遊戲開發。 - 提高應用程式的可靠性和用戶體驗,確保操作不會花費過長的時間。 - 文章內