您好,登錄后才能下訂單哦!
這篇文章主要介紹“TypeScript類型級別和值級別如何區分”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“TypeScript類型級別和值級別如何區分”文章能幫助大家解決問題。
首先,讓我們對值級別編程和類型級別編程進行重要區分。
值級別編程讓我們編寫將在生產中運行的代碼即運行期,并為我們的用戶提供有用的東西。
類型級別編程幫助我們確保代碼在發布之前即編譯期不包含錯誤,在運行期會被完全刪除
JavaScript沒有類型,所以所有JavaScript都是值級別的代碼:
// A simple Javascript function: function sum(a, b) { return a + b; }
TypeScript允許我們將類型注釋添加到JavaScript中,并確保我們編寫的sum函數永遠不會用數字以外的任何東西調用:
// Using type annotations: function sum(a: number, b: number): number { return a + b; }
但TypeScript的類型系統遠比這強大得多。我們編寫的真實代碼有時需要是通用的,并接受我們事先不知道的類型。
在這種情況下,我們可以在尖括號<A,B,…>中定義類型參數然后,我們可以將類型參數傳遞給一個類型級函數,該函數根據輸入類型計算輸出類型:
// Using type level programming: function genericFunction<A, B>(a: A, b: B): DoSomething<A, B> { return doSomething(a, b); }
這就是類型級編程!DoSomething<A,B>
是一種用特殊編程語言編寫的類型級函數,它與我們用于值的語言不同,但同樣強大。讓我們將這種語言稱為類型級TypeScript。
// This is a type-level function: type DoSomething<A, B> = ... // This is a value-level function: const doSomething = (a, b) => ...
類型級TypeScript是一種最小的純函數語言。
在類型級別,函數被稱為泛型類型:它們接受一個或多個類型參數并返回單個輸出類型。下面是一個函數的簡單示例,該函數使用兩個類型參數并將它們包裝在元組中:
type SomeFunction<A, B> = [A, B]; /* ---- ------ ^ \ type return type parameters \-------------------------/ ^ Generic */
類型級別的TypeScript沒有很多功能。畢竟,它是專門為你的代碼做類型約束的!也就是說,它確實有足夠的特性(幾乎)圖靈完備,這意味著你可以用它解決任意復雜的問題。
代碼分支:根據條件執行不同的代碼路徑(相當于值級別if/else關鍵字)。
變量賦值:聲明一個變量并在表達式中使用它(相當于值級別var/let關鍵字)。
函數:可重復使用的邏輯單位,如我們在前面的示例中看到的。
循環:通常通過遞歸。
相等檢查:==但適用于類型!
還有更多!
這是我們將在接下來的章節中學習的語言類型的簡要概述。現在,讓我們開始第一次挑戰吧!
在每一章結束時,你將有一些挑戰需要解決,以將你的新技能付諸實踐。它們看起來像這樣:
namespace challenge { // 1. implement a generic to get the union // of all keys in an object type. type GetAllKeys<Obj> = TODO; type res1 = GetAllKeys<{ a: number }>; type test1 = Expect<Equal<res1, "a">>; }
namespace
是一個鮮為人知的TypeScript功能,它可以讓我們在專用范圍內隔離每個挑戰。
TODO
是占位符。這是您需要更換的!
res1=。。。
是泛型為某些輸入類型返回的類型。您可以用鼠標將其懸停以檢查其當前
type test1=Expect<Equal<res1,…>>
是類型級單元測試。用于判斷TODO
部分的代碼是否正確
在此之前你要先定義好Expect和Equal
type Expect<T extends true> = T; type Equal<X, Y> = (<T>() => T extends { [k in keyof X]: X[k]; } ? 1 : 2) extends <T>() => T extends { [k in keyof Y]: Y[k]; } ? 1 : 2 ? true : false;
準備好迎接你的第一個挑戰了嗎?出發:
/** * 1. The `identity` function takes a value of any type * and returns it. Make it generic! */ namespace genericFunction { function identity(a: TODO): TODO { return a; } let input1 = 10; let res1 = identity(input1); type test1 = Expect<Equal<typeof res1, number>>; let input2 = "Hello"; let res2 = identity(input2); type test2 = Expect<Equal<typeof res2, string>>; }
/** * 2. `safeHead` takes an array, a default value and returns the first element of the array if it isn't empty. Make it generic! */ namespace safeHead { function safeHead(array: TODO[], defaultValue: TODO): TODO { return array[0] ?? defaultValue; } let input1 = [1, 2, 3]; let res1 = safeHead(input1, 0); type test1 = Expect<Equal<typeof res1, number>>; let input2 = ["Hello", "Hola", "Bonjour"]; let res2 = safeHead(input2, "Hi"); type test2 = Expect<Equal<typeof res2, string>>; }
/** * 3. `map` transforms all values in an array to a value of * different type. Make it generic! */ namespace map { function map(array: TODO[], fn: (value: TODO) => TODO): TODO[] { return array.map(fn); } let input1 = [1, 2, 3]; let res1 = map(input1, value => value.toString()); type test1 = Expect<Equal<typeof res1, string[]>>; let input2 = ["Hello", "Hola", "Bonjour"]; let res2 = map(input2, str => str.length); type test2 = Expect<Equal<typeof res2, number[]>>; }
/** * 4. `pipe2` takes a value and pipes it into 2 functions * sequentially. For example, `pipe2(x, f1, f2)` will * result in `f2(f1(x))`. Make it generic! * */ namespace pipe2 { function pipe2( x: TODO, f1: (value: TODO) => TODO, f2: (value: TODO) => TODO ): TODO { return f2(f1(x)); } let res1 = pipe2( [1, 2, 3], arr => arr.length, length => `length: ${length}` ); type test1 = Expect<Equal<typeof res1, string>>; let res2 = pipe2( { name: 'Alice' }, user => user.name, name => name.length > 5 ); type test2 = Expect<Equal<typeof res2, boolean>>; }
關于“TypeScript類型級別和值級別如何區分”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。