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
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
大家好,我是woody,是一名料理創作者,非常努力地在嘗試將複雜的料理簡單化,讓大家也可以體驗到料理的樂趣而我也非常享受料理的過程,今天想跟大家聊聊,除了料理本身,料理創作背後的成本。
Thumbnail
哈囉~很久沒跟各位自我介紹一下了~ 大家好~我是爺恩 我是一名圖文插畫家,有追蹤我一段時間的應該有發現爺恩這個品牌經營了好像.....快五年了(汗)時間過得真快!隨著時間過去,創作這件事好像變得更忙碌了,也很開心跟很多厲害的創作者以及廠商互相合作幫忙,還有最重要的是大家的支持與陪伴🥹。  
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
主要來講宣告函式跟箭頭函式 : 宣告函式(Function Declaration) 語法: function functionName(parameters) { return result; } 特點: 使用 function 關鍵字 函式名稱是必需的 存在函式
Thumbnail
本章節是一個初級的 TypeScript 教學,主要介紹了 TypeScript 中物件導向程式設計的各種核心概念,包括類別、建構子、存取修飾子、繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda 表達式、泛型和反射等。每個概念都通過詳細的解釋和實例代碼來進行深入的介紹。
Thumbnail
本章節旨在介紹TypeScript中的函數,包括其基本結構、如何呼叫函數、函數的參數以及函數的返回值等相關概念。通過本章節,讀者可以學習到如何在TypeScript中使用不同的方式來定義函數,如函數聲明、函數表達式、箭頭函數和匿名函數等。
Thumbnail
此章節旨在介紹TypeScript中的運算符,包括算數運算子、比較運算子、賦值運算子、位元運算子,以及他們的優先等級。每種運算子都以清晰的解釋和代碼範例進行詳細說明,幫助讀者理解並有效地在自己的程式碼中使用。
Thumbnail
本章節旨在介紹 TypeScript 的基本資料型別,包括內建型別、型別轉換、自訂型別、元組、集合、陣列、和字典型別。透過理解和使用這些型別,可以提高代碼的可讀性和可維護性。
Thumbnail
本章節旨在介紹TypeScript的基本語法,包括一般結構、程式進入點、註解以及變數的定義和賦值。這些知識將幫助讀者瞭解TypeScript的基本架構,並且可以開始使用TypeScript進行開發。
※ 函式進階介紹: 箭頭函式: 箭頭函式相比於一般函式,語法相當簡潔。除了少去 function 關鍵字,如果只有一個參數,箭頭函式可以省略括號;只有一行程式碼,就是直接簡單返回一個變數或簡單的表達式,可以省略大括號和 return。例子如下: //一般函式計算平方用的寫法 const squ
Thumbnail
針對 JavaScript 中的原始型別和隱性轉型進行了詳細的探討
Thumbnail
上一篇文章分享了 TypeScript 的定義、前端角色定位,如果你不是很確定「TypeScript 是什麼?」、「TypeScript 作為 JavaScript 的超集,在網頁開發扮演怎麼樣的角色?」這兩個問題的答案,建議可以回到上一篇先了解一下。
Thumbnail
在先前的型別文章中,我們曾經聊過 JavaScript 常用的一些型別,但針對布林這個型別,我們沒有做太多的解釋,原因在於布林值在 JavaScript 會有一個特殊的規則:自動轉型 。 自動轉型可說是讓 JavaScript 為弱型別、且難以管理的最重要的要素,接著就來讓我們來聊聊什麼是自動轉型
Thumbnail
大家好,我是woody,是一名料理創作者,非常努力地在嘗試將複雜的料理簡單化,讓大家也可以體驗到料理的樂趣而我也非常享受料理的過程,今天想跟大家聊聊,除了料理本身,料理創作背後的成本。
Thumbnail
哈囉~很久沒跟各位自我介紹一下了~ 大家好~我是爺恩 我是一名圖文插畫家,有追蹤我一段時間的應該有發現爺恩這個品牌經營了好像.....快五年了(汗)時間過得真快!隨著時間過去,創作這件事好像變得更忙碌了,也很開心跟很多厲害的創作者以及廠商互相合作幫忙,還有最重要的是大家的支持與陪伴🥹。  
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
主要來講宣告函式跟箭頭函式 : 宣告函式(Function Declaration) 語法: function functionName(parameters) { return result; } 特點: 使用 function 關鍵字 函式名稱是必需的 存在函式
Thumbnail
本章節是一個初級的 TypeScript 教學,主要介紹了 TypeScript 中物件導向程式設計的各種核心概念,包括類別、建構子、存取修飾子、繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda 表達式、泛型和反射等。每個概念都通過詳細的解釋和實例代碼來進行深入的介紹。
Thumbnail
本章節旨在介紹TypeScript中的函數,包括其基本結構、如何呼叫函數、函數的參數以及函數的返回值等相關概念。通過本章節,讀者可以學習到如何在TypeScript中使用不同的方式來定義函數,如函數聲明、函數表達式、箭頭函數和匿名函數等。
Thumbnail
此章節旨在介紹TypeScript中的運算符,包括算數運算子、比較運算子、賦值運算子、位元運算子,以及他們的優先等級。每種運算子都以清晰的解釋和代碼範例進行詳細說明,幫助讀者理解並有效地在自己的程式碼中使用。
Thumbnail
本章節旨在介紹 TypeScript 的基本資料型別,包括內建型別、型別轉換、自訂型別、元組、集合、陣列、和字典型別。透過理解和使用這些型別,可以提高代碼的可讀性和可維護性。
Thumbnail
本章節旨在介紹TypeScript的基本語法,包括一般結構、程式進入點、註解以及變數的定義和賦值。這些知識將幫助讀者瞭解TypeScript的基本架構,並且可以開始使用TypeScript進行開發。
※ 函式進階介紹: 箭頭函式: 箭頭函式相比於一般函式,語法相當簡潔。除了少去 function 關鍵字,如果只有一個參數,箭頭函式可以省略括號;只有一行程式碼,就是直接簡單返回一個變數或簡單的表達式,可以省略大括號和 return。例子如下: //一般函式計算平方用的寫法 const squ
Thumbnail
針對 JavaScript 中的原始型別和隱性轉型進行了詳細的探討
Thumbnail
上一篇文章分享了 TypeScript 的定義、前端角色定位,如果你不是很確定「TypeScript 是什麼?」、「TypeScript 作為 JavaScript 的超集,在網頁開發扮演怎麼樣的角色?」這兩個問題的答案,建議可以回到上一篇先了解一下。
Thumbnail
在先前的型別文章中,我們曾經聊過 JavaScript 常用的一些型別,但針對布林這個型別,我們沒有做太多的解釋,原因在於布林值在 JavaScript 會有一個特殊的規則:自動轉型 。 自動轉型可說是讓 JavaScript 為弱型別、且難以管理的最重要的要素,接著就來讓我們來聊聊什麼是自動轉型