iT邦幫忙

2023 iThome 鐵人賽

DAY 10
0
Modern Web

TypeScript 魔法 - 喚醒你的程式碼靈感系列 第 10

Day10 - 我說了算 - 字面值型別(Literal Types)

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20230925/20152047FONMnt6m1V.png

什麼是 Literal Types?

Literal Types 又稱為「字面值型別」或「文字型別」是一種特殊的型別,它允許我們明確指定變數的值必須與特定的字面值互相匹配。這些字面值可以是數字、字串、布林值,甚至符號。字面值型別的使用使我們能夠建立具有固定值的變數,並且在某些情境下非常實用,有助於提高代碼的可讀性和可維護性,以及增強型別檢查的準確性。

數字 Literal Types

聯合型別為基礎,數字字面值型別的應用範例如下:

let num: 1 | 2 | 3 | 4 | 5;

num = 1; // 正確
num = 2; // 正確
num = 3; // 正確
num = 4; // 正確
num = 5; // 正確
num = 6; // 錯誤,因為 6 不在 num 變數允許的值列表中

https://ithelp.ithome.com.tw/upload/images/20230925/20152047oKL6zKzVfY.png
在這種情況下, num 不再是 number 型別,而是一個特定的 1 | 2 | 3 | 4 | 5 數字值的子集。

字串 Literal Types

聯合型別為基礎,字串字面值型別的應用範例如下:

let colors: 'red' | 'blue' | 'yellow';

colors = 'red'; // 正確
colors = 'blue'; // 正確
colors = 'yellow'; // 正確
colors = 'green'; // 錯誤,因為 'green' 不在 colors 變數允許的值列表中

https://ithelp.ithome.com.tw/upload/images/20230925/2015204761kAGiugAM.png
在這種情況下,colors 不再是 string 型別,而是一個特定的 'red' | 'blue' | 'yellow' 字串值的子集。

布林 Literal Types

聯合型別為基礎,布林字面值型別的應用範例如下:

let isCompleted: true | false; // 實際上等於 let isCompleted: boolean;
isCompleted = true; // 正確
isCompleted = false; // 正確
isCompleted = 1; // 錯誤,類型 'number' 不可指派給類型 'boolean'
isCompleted = '肉鬆'; // 錯誤,類型 'string' 不可指派給類型 'boolean'

函式 Literal Types 實際應用情境

延伸Day09-型別們,聯合吧!聯合型別的範例。

在函式中,我們新增名為 resultConversion 的參數,並允許從外部傳入字面值型別 as-numberas-text ,用於判斷處理數字或字串。

第一種邏輯:

  1. 先判斷輸入的型別(numberstring
  2. 再判斷字面值型別(as-numberas-text
function combine(
  input1: number | string,
  input2: number | string,
  resultConversion: string
) {
  let result;
  if (typeof input1 === 'number' && typeof input2 === 'number') {
    result = input1 + input2;
  } else {
    result = input1.toString() + input2.toString();
  }

  if (resultConversion === 'as-number') {
    return +result;
  } else {
    return result.toString();
  }
}

const combinedAges = combine(30, 27, 'as-number');
console.log(combinedAges); // 57

const combinedStringAges = combine('30', '27', 'as-number');
console.log(combinedStringAges); // 3027

const combinedNames = combine('Rousong', 'Chen', 'as-text');
console.log(combinedNames); // RousongChen

第二種邏輯:

同時判斷輸入的型別與字面值型別(numberstringas-numberas-text

function combine(
  input1: number | string,
  input2: number | string,
  resultConversion: string
) {
  let result;
  if (
    (typeof input1 === 'number' && typeof input2 === 'number') ||
    resultConversion === 'as-number'
  ) {
	result = +input1 + +input2; 
    // 若沒有強制轉成 number 型別,TypeScript 會報錯
  } else {
    result = input1.toString() + input2.toString();
  }
  return result;
};

const combinedAges = combine(30, 27, 'as-number');
console.log(combinedAges); // 57

const combinedStringAges = combine('30', '27', 'as-number');
console.log(combinedStringAges); // 57

const combinedNames = combine('Rousong', 'Chen', 'as-text');
console.log(combinedNames); // RousongChen

接著,我們繼續探討字面值型別的概念,假設 resultConversion 參數不應該是任何字串,而是特定的 as-numberas-text,我們可以使用聯合型別搭配字面值型別。

function combine(
  input1: number | string,
  input2: number | string,
  resultConversion: 'as-number' | 'as-text'
) {
  let result;
  if (
    (typeof input1 === 'number' && typeof input2 === 'number') ||
    resultConversion === 'as-number' 
    // 若給予特定外的字面值型別,TypeScript 會報錯
  ) {
    result = +input1 + +input2;
  } else {
    result = input1.toString() + input2.toString();
  }
  return result;
};

const combinedAges = combine(30, 27, 'as-number');
console.log(combinedAges); // 57

const combinedStringAges = combine('30', '27', 'as-number');
console.log(combinedStringAges); // 57

const combinedNames = combine('Rousong', 'Chen', 'as-text');
console.log(combinedNames); // RousongChen

本日重點

  1. 透過字面值型別要求變數或屬性的值必須精確分配指定的字面值。
  2. 字面值型別是一種限制型別被明確定義的方式,同時也改善了聯合型別的定義,以避免型別變得過於廣泛的問題。

參考


上一篇
Day09 - 型別們,聯合吧!(Union Types)
下一篇
Day11 - TypeScript 的秘密武器(上) - 型別別名(Type Aliases)
系列文
TypeScript 魔法 - 喚醒你的程式碼靈感30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言