TS 筆記 | TypeScript 進階

更新於 發佈於 閱讀時間約 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
留言分享你的想法!
avatar-img
Jeremy Ho的沙龍
19會員
37內容數
這個專題用來存放我在學習網頁開發時的心得及知識。
Jeremy Ho的沙龍的其他內容
2023/11/16
TypeScript 基礎語法
Thumbnail
2023/11/16
TypeScript 基礎語法
Thumbnail
2023/11/13
JavaScript callback, promise, async-await
Thumbnail
2023/11/13
JavaScript callback, promise, async-await
Thumbnail
2023/10/09
String 基本操作方法
Thumbnail
2023/10/09
String 基本操作方法
Thumbnail
看更多
你可能也想看
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
介紹朋友新開的蝦皮選物店『10樓2選物店』,並分享方格子與蝦皮合作的分潤計畫,註冊流程簡單,0成本、無綁約,推薦給想增加收入的讀者。
Thumbnail
介紹朋友新開的蝦皮選物店『10樓2選物店』,並分享方格子與蝦皮合作的分潤計畫,註冊流程簡單,0成本、無綁約,推薦給想增加收入的讀者。
Thumbnail
本文介紹 Kotlin 中類別的定義方法與實際應用,以及類別的好處和優點。透過實例說明,讓讀者更了解如何在 Kotlin 中使用類別來實現相關功能。
Thumbnail
本文介紹 Kotlin 中類別的定義方法與實際應用,以及類別的好處和優點。透過實例說明,讓讀者更了解如何在 Kotlin 中使用類別來實現相關功能。
Thumbnail
這一篇會介紹非常重要的 JavaScript 函式概念 - 高階函式(Higher-order function),高階函數是將一個或多個函數作為參數,或將一個函數作為結果返回的函數。在本文中,我們將深入探討什麽是高階函數、使用高階函數的好處以及如何在實際應用中使用高階函數,函式導向是什麼?
Thumbnail
這一篇會介紹非常重要的 JavaScript 函式概念 - 高階函式(Higher-order function),高階函數是將一個或多個函數作為參數,或將一個函數作為結果返回的函數。在本文中,我們將深入探討什麽是高階函數、使用高階函數的好處以及如何在實際應用中使用高階函數,函式導向是什麼?
Thumbnail
當我們需要給某個系統或應用程序添加一種新的語言或表達式時,解譯器模式就派上了用場。這種模式提供了一種將句子或表達式分解成多個令牌的方法,然後根據這些令牌進行解釋或解析。
Thumbnail
當我們需要給某個系統或應用程序添加一種新的語言或表達式時,解譯器模式就派上了用場。這種模式提供了一種將句子或表達式分解成多個令牌的方法,然後根據這些令牌進行解釋或解析。
Thumbnail
👨‍💻簡介 本文快速介紹了 Go 語言中的各種運算符,從數學計算到邏輯判斷,包括自增自減、賦值、比較和位運算。透過實例和清晰的解釋,快速掌握如何在程式中運用這些運算符。
Thumbnail
👨‍💻簡介 本文快速介紹了 Go 語言中的各種運算符,從數學計算到邏輯判斷,包括自增自減、賦值、比較和位運算。透過實例和清晰的解釋,快速掌握如何在程式中運用這些運算符。
Thumbnail
👨‍💻簡介 Go 語言有各種資料型別,分為基本型別和複合型別。基本型別包括: 整數、浮點數、布林值、字串 複合型別包括: 陣列、片段、結構、函式、對映、通道、介面 等。 整數型別 整數型別有許多種,像是 int8、int16、int32、int64。我們可以依據實際需求選擇。
Thumbnail
👨‍💻簡介 Go 語言有各種資料型別,分為基本型別和複合型別。基本型別包括: 整數、浮點數、布林值、字串 複合型別包括: 陣列、片段、結構、函式、對映、通道、介面 等。 整數型別 整數型別有許多種,像是 int8、int16、int32、int64。我們可以依據實際需求選擇。
Thumbnail
👨‍💻簡介 在 Golang 中,你可以使用不同的方式來宣告變數和常數。宣告變數時,可以直接指定值,或者使用型別推導,更簡單地用 := 來宣告局部變數。另外,還可以一次宣告多個變數,相同型別的變數可以一起宣告,或者使用括號宣告不同型別的變數。常數則使用 const 關鍵字宣告,確保值不變
Thumbnail
👨‍💻簡介 在 Golang 中,你可以使用不同的方式來宣告變數和常數。宣告變數時,可以直接指定值,或者使用型別推導,更簡單地用 := 來宣告局部變數。另外,還可以一次宣告多個變數,相同型別的變數可以一起宣告,或者使用括號宣告不同型別的變數。常數則使用 const 關鍵字宣告,確保值不變
Thumbnail
  程式中很常會看到千奇百怪的運算式,這些運算式都隱藏著各種運算元和運算子,這些是什麼呢?讓我們來一探究竟。   運算元是指變數、常數這類(如:A、B、C、Data、123等),運算子是指運算符號(如:+、-、*、/、%、==、<、&&等這類型),這邊就要介紹C#的運算子以及怎麼使用。
Thumbnail
  程式中很常會看到千奇百怪的運算式,這些運算式都隱藏著各種運算元和運算子,這些是什麼呢?讓我們來一探究竟。   運算元是指變數、常數這類(如:A、B、C、Data、123等),運算子是指運算符號(如:+、-、*、/、%、==、<、&&等這類型),這邊就要介紹C#的運算子以及怎麼使用。
Thumbnail
本篇文章將會記錄Microsoft關於數字計算相關的知識,以及紀錄這些計算的專有名詞,補足闕漏的知識。
Thumbnail
本篇文章將會記錄Microsoft關於數字計算相關的知識,以及紀錄這些計算的專有名詞,補足闕漏的知識。
Thumbnail
函式(Function)、傳值法、傳位址法、傳參考法
Thumbnail
函式(Function)、傳值法、傳位址法、傳參考法
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News