Try   HackMD

以「陰陽」理解 TypeScript 的 Type 和 Value 🌗

Value(值)

value 就是在執行時期,能夠在表達式中引用的變數。

例如 let x = 5 會建立一個叫做 xvalue,而且可以透過 console.log(x) 把值印出來。

🌕 我喜歡用陰陽的來形容 value

ES6(JavaScript 本來就有的):

  1. letconstvar 宣告的 value
  2. function
  3. class
  4. 引用 value 的 import

TypeScript 特有的:

  1. enum
  2. 包含 value 的 namespacemodule

Type(型別)

🌑 我會用來形容 type

我們並沒辦法拿型別執行來做運算,因為它們僅僅是用來標註型別用的,且經編譯後就會丟棄這些型別的訊息。

在 TypeScript 能以下列方法建立 type

  1. type
    例如 type sn = number | string
  2. interface
    例如 interface I { x: number[] }
  3. class 💙
    例如 class C { }
  4. enum 💙
    例如 enum E { A, B, C }
  5. 引用 type 的 import

💙 能同時建立 ValueType 的特例

  1. class
  2. enum

稱它們為特例的原因是,由這兩個關鍵字宣告出來的東西,同時是 value 也是 type。且不像一般的 type,它們經編譯後依然會被留下來。

class 範例

// 宣告叫做 Student 的 class class Student { name: string age: number constructor (name: string, age: number) { /* ... */ } } // 可以將 `Student` 當 value 用: // 例如透過 new 來建立一個實例 const sean = new Student('黃省喬', 24) // 也可以將 Student 當 type 用: // 例如用來宣告列表型別 `Students` type Students = Student[] // 或是當作參數的型別 const 點名 = (student: Student) => { console.log(`🙋 ${student.name}`) } 點名(sean)

enum 範例

// 宣告叫做 Status 的 enum enum Status { idle = 0, loading = 1, success = 2, failure = 3, } const isSuccess = (status: Status) => { return status === Status.success }

可至 TypeScript Playground 查看這段程式碼的 enum 是如何被編譯的

如何打破「陰陽」的隔閡?

也就是,該如何反推某個來得到它的型別? → typeof

只能從某個 🌕 value 得到它的 🌑 type;
反過來想從 🌑 type 得到 🌕 value 則是辦不到的。(上述特例除外)

// 宣告一個物件🌕 const sushi = { name: '🍣', price: 40, isRaw: true, } // 使用 `typeof` 關鍵字取得物件的型別🌑 type Food = typeof sushi // { name: string, price: number, isRaw: boolean } // 取得 `Food` 的所有鍵的型別🌑 type KeyOfFood = keyof Food // "name" | "price" | "isRaw" // 取得 `Food` 的所有值的型別🌑 type ValueOfFood = Food[KeyOfFood] // string | number | boolean

⚠️ 此處的 typeof 是 TypeScript 的關鍵字,注意別和 JavaScript 的運算子 typeof 混淆了!

參考資料

https://www.typescriptlang.org/docs/handbook/declaration-files/deep-dive.html