從不同的角度看,TS 中的類型到底是什么?

0. 作者以及原文介紹
作者是 Dr. Axel Rauschmayer,號稱”德國阮一峰“,本文原文來自于他的博客:https://2ality.com/2020/02/understanding-types-typescript.html,不熟悉他的可以關注一下他的博客。
以下是原文:
1. 每個角度都從這三個問題來解釋
以下三個問題對于理解類型是如何工作的非常重要,需要從這兩個角度中的每一個角度來回答。
myVariable的類型MyType意味著什么?
let myVariable: MyType = /*...*/;
Sourcetype可以分配給TargetType嗎?
let source: SourceType = /*...*/;
let target: TargetType = source;
TypeUnion是如何從Type1、Type2和Type3衍生而來的?
type TypeUnion = Type1 | Type2 | Type3;
2. 角度 1:類型是一組值
從這個角度來看,類型是一組值:
如果
myVariable具有MyType類型,這意味著可以分配給myVariable的所有值都必須是集合MyType的元素。如果
Sourcetype可以分配給TargetType,那么Sourcetype是TargetType的子集。因此,TargetType也允許SourceType所允許的所有值。類型
Type1、Type2和Type3的聯(lián)合類型是定義它們的集合在集合論中的并集。
3. 角度 2:類型兼容關系
從這個角度來看,我們不關心值以及它們在執(zhí)行代碼時如何流動。相反,我們采取了一種更為靜態(tài)的觀點:
源代碼有個位置,每個位置都有一個靜態(tài)類型。在支持 Typescript 的編輯器中,如果我們將鼠標懸停在某個位置的上方,就可以看到該位置的靜態(tài)類型。 當源位置通過賦值、函數(shù)調用等方式連接到目標位置時,源位置的類型必須與目標位置的類型兼容。Typescript 規(guī)范通過所謂的類型關系定義類型的兼容性。 類型關系分配兼容性定義了源類型 S何時可以分配給目標類型T:S和T都是一樣的類型S或者T是 any 類型。等等
讓我們考慮以下問題:
如果 myVariable的靜態(tài)類型可以分配給MyType,那么myVariable就具有類型MyType如果 SourceType和TargetType是互相兼容的,那么SourceType可以分配給TargetType聯(lián)合類型的工作方式是通過類型關系成員定義的。
類型系統(tǒng)一個有趣的特點是,同一個變量在不同的位置可以有不同的靜態(tài)類型:
const arr = [];
// %inferred-type: any[]
arr;
arr.push(123);
// %inferred-type: number[]
arr;
arr.push('abc');
// %inferred-type: (string | number)[]
arr;
4. 標準類型系統(tǒng)和結構類型系統(tǒng)
靜態(tài)類型系統(tǒng)的職責之一是確定兩個靜態(tài)類型是否兼容:
實際參數(shù)的靜態(tài)類型 U(例如,通過函數(shù)調用提供) 對應形式參數(shù)的靜態(tài)類型 T(指定為函數(shù)定義的一部分)
這通常意味著要檢查 U 是否是 T 的子類型。這種檢查的兩種方法(大致)是:
在標準類型中,如果兩個靜態(tài)類型具有相同的標識(“名稱”) ,則它們是相等的。一種類型是另一種類型的子類型,它們的子類型關系是顯式聲明的。
具有標準類型的語言有 c++ 、 Java、 c# 、 Swift 和 Rust
在結構類型系統(tǒng)中,如果兩個靜態(tài)類型具有相同的結構(如果它們的部分具有相同的名稱和相同的類型) ,則它們是相等的。如果 U 包含 T 的所有部分(可能還包括其他部分) ,并且 U 的每個部分都包含 T 的相應部分的子類型,那么一種類型 U 就是另一種類型 T 的子類型。
具有結構類型的語言有 ocaml/reasonml、 Haskell 和 TypeScript
下面的代碼在標準類型系統(tǒng)中產生類型錯誤(第 A 行) ,但在 Typescript 的結構類型系統(tǒng)中是合法的,因為類 A 和類 B 具有相同的結構:
class A {
name = 'A';
}
class B {
name = 'B';
}
const someVariable: A = new B(); // (A)
Typescript 的接口在結構上也能工作——它們不需要實現(xiàn)來匹配:
interface Point {
x: number;
y: number;
}
const point: Point = {x: 1, y: 2}; // OK
5. 進一步閱讀
Chapter “Type Compatibility” in the TypeScript Handbook[1] Section “TypeRelationships” in the TypeScript Specification[2]
如果翻譯得不對的地方希望您可以幫忙指出來。
參考資料
Chapter “Type Compatibility” in the TypeScript Handbook: https://www.typescriptlang.org/docs/handbook/type-compatibility.html
[2]Section “TypeRelationships” in the TypeScript Specification: https://github.com/microsoft/TypeScript/blob/master/doc/spec.md#311-type-relationships
推薦閱讀
最后
如果你覺得這篇內容對你挺有啟發(fā),我想邀請你幫我三個小忙:
點個「在看」,讓更多的人也能看到這篇內容(喜歡不點在看,都是耍流氓 -_-)
歡迎加我微信「 sherlocked_93 」拉你進技術群,長期交流學習...
關注公眾號「前端下午茶」,持續(xù)為你推送精選好文,也可以加我為好友,隨時聊騷。

