從兩個角度理解 TypeScript 中的類型是什麼?

做者:Dr. Axel Rauschmayer

翻譯:瘋狂的技術宅html

原文:https://2ality.com/2020/02/un...前端

未經容許嚴禁轉載git

TypeScript中的類型是什麼?本文中描述了兩種有助於理解它們的觀點。程序員

每一個角度三個問題

如下三個問題對於理解類型如何工做很是重要,而且須要從兩個角度分別回答。github

  1. myVariable 具備 MyType 類型是什麼意思?
let myVariable: MyType = /*...*/;
  1. SourceType 是否能夠分配給 TargetType
let source: SourceType = /*...*/;
   let target: TargetType = source;
  1. TypeUnion 是如何從 Type1Type2Type3 派生的?
type TypeUnion = Type1 | Type2 | Type3;

觀點1:類型是值的集合

從這個角度來看,類型是一組值:面試

  1. 若是 myVariable 的類型爲 MyType,則意味着全部能夠分配給 myVariable 的值都必須是 MyType 集合的元素。
  2. SourceType 可分配給 TargetTypeSourceTypeTargetType 的子集。結果全部能被 SourceType 接受的值也被 TargetType 接受。
  3. 類型 Type1Type2Type3 的類型聯合是定義它們集合的集合理論 union。

觀點2:類型兼容性關係

從這個角度來看,咱們不關心值自己以及在執行代碼時它們是如何流動的。相反,咱們採起了更加靜態的觀點:typescript

  • 源代碼中包含 location,每一個 location 都有一個靜態類型。在支持 TypeScript 的編輯器中,若是將光標懸停在 location 上方,則能夠看到該 location 的靜態類型。
  • 當源 location 經過分配、函數調用等鏈接到目標 location 時,則源 location 的類型必須與目標 location 的類型兼容。 TypeScript 規範經過所謂的類型關係定義類型兼容性。
  • 類型關係分配兼容性定義何時把源類型 S 分配給目標類型 Tsegmentfault

    • ST 是相同的類型。
  • STany 類型。服務器

讓咱們考慮如下問題:微信

  1. 若是將 myVariable 的靜態類型分配給 MyType,則 myVariable 的類型爲 MyType
  2. 若是 SourceType 是兼容分配的,則能夠將它們分配給 TargetType
  3. 經過類型關係apparent 成員定義類型 union 的工做方式。

TypeScript 類型系統的一個有趣特徵是,同一變量在不一樣位置能夠具備不一樣的靜態類型:

const arr = [];
// %inferred-type: any[]
arr;

arr.push(123);
// %inferred-type: number[]
arr;

arr.push('abc');
// %inferred-type: (string | number)[]
arr;

名義類型系統與結構類型系統

靜態類型系統的職責之一是肯定兩種靜態類型是否兼容:

  • 實際參數的靜態類型 U(例如,經過函數調用提供)
  • 對應形式參數的靜態類型 T(在函數定義中指定)

這一般意味着檢查 U 是否爲 T 的子類型。大體有兩種檢查方法:

  • 名義類型系統中,兩個靜態類型若是具備相同的標識(「名稱」)則相等。若是明確聲明瞭它們的子類型關係,則一種類型是另外一種類型的子類型。
  • 名義類型的語言爲 C ++、Java、C#、Swift 和 Rust。
  • 結構類型系統中,兩個靜態類型具備相同的結構(若是它們具備相同的名稱和相同的類型)則相等。若是 U 具備 T 的全部部分(可能還有其餘),而且 U 的每一個部分具備 T 的相應部分的子類型,則類型 U 是另外一種類型 T 的子類型。
  • 具備結構化類型的語言爲 OCaml/ReasonML、Haskell 和 TypeScript。

如下代碼在名義類型系統中會產生類型錯誤(A 行),但在 TypeScript 的結構類型系統中是合法的,由於類 A 和類 B 具備相同的結構:

class A {
  name = 'A';
}
class B {
  name = 'B';
}
const someVariable: A = new B(); // (A)

TypeScript 的 interface 在結構上也能夠正常工做 —— 沒必要爲了匹配而實現它們:

interface Point {
  x: number;
  y: number;
}
const point: Point = {x: 1, y: 2}; // OK

進一步閱讀


本文首發微信公衆號:前端先鋒

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章

歡迎繼續閱讀本專欄其它高贊文章:


相關文章
相關標籤/搜索