[Day12] TS:什麼!型別還有遞迴(recursion)的概念?用組合技實作 SnakeToCamelCase
這是我們今天要聊的內容,老樣的,如果你已經可以輕鬆看懂,歡迎直接左轉去看我同事 Andy 精彩的文章 — 「前端工程師學習 DevOps 之路」。
什麼是遞迴函式(recursive function)
遞迴(recursion)是寫程式時會使用到的概念,特別是在刷題的時候!?(推薦參考:Day 02 : Fibonacci 斐波那契 @ 30 天用 JavaScript 刷題刷起來!)
遞迴函式(recursive function)簡單來說就是在一個函式中呼叫它自己,舉例來說:
const countDown = (num) => {
console.log(num);
return num > 0 ? countDown(num - 1) : 0;
};
在這個 countDown
函式中會去呼叫它自己(countDown
):
recursive function 一定要有一個終止的條件,以這裡來說,就是當 num <= 0
時,就不會再次呼叫自己。
TypeScript 中也能使用遞迴
回到 TypeScript,在 TypeScript 中的 Type Alias 和 Conditional Type 也一樣可以使用遞迴函式的概念。
Recursive Type Aliases
來比較一下下面這兩個例子:
// 沒有使用 Recursive Type
type ValueOrArray<T> = T | T[];
// 使用了 Recursive Type Aliases
type ValueOrNestedArray<T> = T | ValueOrNestedArray<T>[];
先看上面的 ValueOrArray<T>
這個 Utility Type,它的概念很簡單,它產生的型別可以是原本帶入 <>
內的型別,或者是這個型別所建立的陣列:
type NumberArray = ValueOrArray<number>;
let numberArray: NumberArray = 0;
numberArray = [0, 1];
// ERROR: Type '[number]' is not assignable to type 'number'
numberArray = [0, [1]];
我們可以看到要滿足 ValueOrArray<number>
的話,可以是一般的 number
,或者是 number[]
,但如果是 nested 的 number[]
,TS 就會報錯:
接著我們看到第二個例子 ValueOrNestedArray<T>
, 你會發現到 T | ValueOrNestedArray<T>[]
指的是它除了可以是原本帶入 <>
的型別外,還在這個 Type 裡呼叫了它自己,這麼做的概念就很像是:
type ValueOrNestedArray<T> = T | T[] | T[][] | T[][][] | ...;
因此,如果要滿足 ValueOrNestedArray<number>
,只要是 number array 都可以,即使它是 nested 的 number array:
type NestedNumberArray = ValueOrNestedArray<number>;
let nestedNumberArray: NestedNumberArray = 0;
nestedNumberArray = [0, 1];
nestedNumberArray = [0, [1]];
nestedNumberArray = [0, [1, [2]]];
// ERROR: Type 'string' is not assignable to type 'ValueOrNestedArray<number>'
nestedNumberArray = ['0', [1]];
除非帶入陣列的值不是 number
,否則都是能夠滿足 ValueOrNestedArray<number>
的,而這就是遞迴在 TypeScript 中的使用 — 在一個 Utility Type 中呼叫自己。
遞迴概念也可以使用在 Conditional Types 中,讓我們回到今天最開始的那個範例。
SnakeToCamelCase 的使用方式
讓我們來看一下今天的主角 SnakeToCamelCase
,它的作用會像這樣:
type T1 = SnakeToCamelCase<'this_is_snake_case'>; // "thisIsSnakeCase"
type T2 = SnakeToCamelCase<'This_Is_Strange_Case'>; // "thisIsStrangeCase"
type T3 = SnakeToCamelCase<'IDontKnowThis'>; // "IDontKnowThis"
- 如果原本傳入的字串型別符合 snake case 的話,它可以把原本是
snake_case
的字串型別轉換成CamelCase
。 - 如果原本傳入的字串型別不符合 snake case 的話,則會直接回傳原本的型別回去。
SnakeToCamelCase
是修改自 ts-case-convert 中的ToCamel
這個 Utility Type。