[TypeScript] 编程实践之1: Google的TypeScript代码风格3:类型
TypeScript語言規(guī)范
- 3 類型
- 3.1 Any類型
- 3.2 基本類型
- 3.2.1 Number類型
- 3.2.2 Boolean類型
- 3.2.3 String類型
- 3.2.4 Symbol類型
- 3.2.5 Void類型
- 3.2.6 Null類型
- 3.2.7 Undefined類型
- 3.2.8 Enum類型
- 3.2.9 String類型
- 3.3 Object類型
- 3.3.1 命名類型引用
- 3.3.2 Array類型
- 3.3.3 Tuple類型
- 3.3.4 Function類型
- 3.3.5 Constructor類型
- 3.3.6 Members
- 3.4 Union類型
- 3.5 Intersection類型
- 3.6 Type參數(shù)
- 3.6.1 Type Parameter列表
- 3.6.2 Type Argument列表
- 3.6.3 This類型
- 3.7 命名類型
- 3.8 指定類型
- 3.8.1 預(yù)定義類型
- 3.8.2 類型引用
- 3.8.3 Object類型文法
- 3.8.4 Array類型文法
- 3.8.5 Tuple類型文法
- 3.8.6 Union類型文法
- 3.8.7 Intersection類型文法
- 3.8.8 Function類型文法
- 3.8.9 Constructor類型文法
- 3.8.10 類型查詢
- 3.8.11 This類型推導(dǎo)
- 3.9 指定成員
- 3.9.1 屬性簽名
- 3.9.2 Call簽名
- 3.9.2.1 Type參數(shù)
- 3.9.2.2 參數(shù)列表
- 3.9.2.3 Return類型
- 3.9.2.4 特定簽名
- 3.9.3 Construct簽名
- 3.9.4 索引簽名
- 3.9.5 方法簽名
- 3.10 類型別名
- 3.11 Type關(guān)系
- 3.11.1 明顯成員
- 3.11.2 Type和Member類型
- 3.11.3 子類型和超類型
- 3.11.4 賦值兼容性
- 3.11.5 額外屬性
- 3.11.6 上下文簽名實例化
- 3.11.7 類型推導(dǎo)
- 3.11.8 遞歸類型
- 3.12 加寬類型
3 類型
TypeScript將可選的靜態(tài)類型添加到JavaScript。類型用于對程序?qū)嶓w(例如函數(shù),變量和屬性)施加靜態(tài)約束,以便編譯器和開發(fā)工具可以在軟件開發(fā)期間提供更好的驗證和幫助。 TypeScript的靜態(tài)編譯時類型系統(tǒng)緊密地模擬了JavaScript的動態(tài)運行時類型系統(tǒng),從而使程序員可以準確地表達其程序運行時預(yù)期存在的類型關(guān)系,并通過TypeScript編譯器對這些假設(shè)進行了預(yù)先驗證。 TypeScript的類型分析完全在編譯時進行,并且不增加程序執(zhí)行的運行時開銷。
TypeScript中的所有類型都是單個頂部類型的子類型,稱為Any類型。 any關(guān)鍵字引用此類型。 Any類型是可以無限制地表示任何JavaScript值的一種類型。所有其他類型都分類為基本類型,對象類型,聯(lián)合類型,交集類型或類型參數(shù)。這些類型在其值上引入了各種靜態(tài)約束。
基本類型是Number,Boolean,String,Symbol,Void,Null和Undefined類型以及用戶定義的枚舉類型。 number,boolean,string,symbol和void關(guān)鍵字分別引用Number,Boolean,String,Symbol和Void基本類型。 Void類型的存在純粹是為了指示不存在值,例如在沒有返回值的函數(shù)中。不可能顯式引用Null和Undefined類型-使用null和undefined文字只能引用這些類型的值。
對象類型是所有類,接口,數(shù)組,元組,函數(shù)和構(gòu)造函數(shù)類型。類和接口類型是通過類和接口聲明引入的,并通過在其聲明中為其指定的名稱進行引用。類和接口類型可以是具有一個或多個類型參數(shù)的通用類型。
聯(lián)合類型表示具有多種類型之一的值,交集類型表示同時具有多種類型的值。
類,屬性,函數(shù),變量和其他語言實體的聲明將類型與這些實體相關(guān)聯(lián)。形成類型并將其與語言實體關(guān)聯(lián)的機制取決于特定類型的實體。例如,命名空間聲明將命名空間與匿名類型相關(guān)聯(lián),該匿名類型包含與該命名空間中導(dǎo)出的變量和函數(shù)相對應(yīng)的一組屬性,而函數(shù)聲明則將該函數(shù)與匿名類型相關(guān)聯(lián),該匿名類型包含與參數(shù)相對應(yīng)的調(diào)用簽名并返回函數(shù)的類型。類型可以通過顯式類型注釋與變量關(guān)聯(lián),例如
var x: number;或通過隱式類型推斷,如
var x = 1;推斷“ x”的類型為Number原語類型,因為這是用于初始化“ x”的值的類型。
3.1 Any類型
Any類型用于表示任何JavaScript值。 Any類型的值支持與JavaScript中的值相同的操作,并且對Any值的操作執(zhí)行最少的靜態(tài)類型檢查。 具體來說,可以通過Any值訪問任何名稱的屬性,并且Any值可以用作帶有任何參數(shù)列表的函數(shù)或構(gòu)造函數(shù)。
any關(guān)鍵字引用Any類型。 通常,在沒有顯式提供類型并且TypeScript無法推斷一個類型的地方,將假定為Any類型。
Any類型是所有類型的超類型,并且可以分配給所有類型或從所有類型分配。
一些例子:
var x: any; // Explicitly typed var y; // Same as y: any var z: { a; b; }; // Same as z: { a: any; b: any; }function f(x) { // Same as f(x: any): void console.log(x); }3.2 基本類型
基本類型為Number,Boolean,String,Symbol,Void,Null和Undefined類型以及所有用戶定義的枚舉類型。
3.2.1 Number類型
Number原語類型對應(yīng)于類似命名的JavaScript原語類型,并表示雙精度64位格式IEEE 754浮點值。
number關(guān)鍵字引用Number原語類型,并且數(shù)字文字可用于寫入Number原語類型的值。
為了確定類型關(guān)系(第第3.11節(jié))和訪問屬性(第4.13節(jié)),Number原語類型表現(xiàn)為具有與全局接口類型“ Number”相同屬性的對象類型。
一些例子:
var x: number; // Explicitly typed var y = 0; // Same as y: number = 0 var z = 123.456; // Same as z: number = 123.456 var s = z.toFixed(2); // Property of Number interface3.2.2 Boolean類型
布爾基元類型對應(yīng)于類似命名的JavaScript基元類型,并表示邏輯值true或false。
boolean關(guān)鍵字引用Boolean基本類型,true和false文字引用兩個Boolean真值。
為了確定類型關(guān)系(第3.11節(jié))和訪問屬性(第4.13節(jié)),布爾基元類型的行為與對象類型具有與全局接口類型“布爾”相同的屬性。
一些例子:
var b: boolean; // Explicitly typed var yes = true; // Same as yes: boolean = true var no = false; // Same as no: boolean = false3.2.3 String類型
String原語類型對應(yīng)于類似命名的JavaScript原語類型,并表示存儲為Unicode UTF-16代碼單元的字符序列。
string關(guān)鍵字引用String原語類型,并且字符串文字可用于寫入String原語類型的值。
為了確定類型關(guān)系(第3.11節(jié))和訪問屬性(第4.13節(jié)),String基本類型的行為與具有與全局接口類型’String’相同的屬性的對象類型相同。
一些例子:
var s: string; // Explicitly typed var empty = ""; // Same as empty: string = "" var abc = 'abc'; // Same as abc: string = "abc" var c = abc.charAt(2); // Property of String interface3.2.4 Symbol類型
Symbol原語類型對應(yīng)于類似命名的JavaScript原語類型,并表示可以用作對象屬性鍵的唯一標記。
symbol關(guān)鍵字引用Symbol基本類型。 使用具有許多方法和屬性的全局對象“ Symbol”可以獲得符號值,并且可以將其作為函數(shù)調(diào)用。 特別是,全局對象’Symbol’定義了許多眾所周知的符號(2.2.3),它們可以以類似于標識符的方式使用。 請注意,“符號”對象僅在ECMAScript 2015環(huán)境中可用。
為了確定類型關(guān)系(第3.11節(jié))和訪問屬性(第4.13節(jié)),Symbol原語類型表現(xiàn)為具有與全局接口類型’Symbol’相同屬性的對象類型。
一些例子:
var secretKey = Symbol(); var obj = {}; obj[secretKey] = "secret message"; // Use symbol as property key obj[Symbol.toStringTag] = "test"; // Use of well-known symbol3.2.5 Void類型
由void關(guān)鍵字引用的Void類型表示不存在值,并用作沒有返回值的函數(shù)的返回類型。
Void類型的唯一可能值為null和undefined。 Void類型是Any類型的子類型,是Null和Undefined類型的超類型,但是Void與其他所有類型都不相關(guān)。
注意:我們可能會考慮禁止聲明Void類型的變量,因為它們沒有用處。 但是,由于允許將Void作為泛型類型或函數(shù)的類型參數(shù),因此不允許Void屬性或參數(shù)是不可行的。
3.2.6 Null類型
Null類型對應(yīng)于類似命名的JavaScript原語類型,并且是null文字的類型。
null文字引用Null類型的唯一值。 無法直接引用Null類型本身。
Null類型是除Undefined類型之外的所有類型的子類型。 這意味著對于所有基本類型,對象類型,聯(lián)合類型,交集類型和類型參數(shù)(包括Number和Boolean基本類型),null均被視為有效值。
一些例子:
var n: number = null; // Primitives can be null var x = null; // Same as x: any = null var e: Null; // Error, can't reference Null type3.2.7 Undefined類型
Undefined類型對應(yīng)于類似命名的JavaScript原語類型,并且是undefined文字的類型。
未定義文字表示給所有未初始化變量的值,并且是Undefined類型的唯一值。 無法直接引用未定義類型本身。
未定義類型是所有類型的子類型。 這意味著對于所有基本類型,對象類型,聯(lián)合類型,交集類型和類型參數(shù),未定義均被視為有效值。
一些例子:
var n: number; // Same as n: number = undefined var x = undefined; // Same as x: any = undefined var e: Undefined; // Error, can't reference Undefined type3.2.8 Enum類型
枚舉類型是Number原語類型的不同用戶定義的子類型。 枚舉類型使用枚舉聲明(第9.1節(jié))聲明,并使用類型引用(第3.8.2節(jié))進行引用。
枚舉類型可分配給Number原語類型,反之亦然,但不同的枚舉類型不能相互分配。
3.2.9 String類型
專用簽名(第3.9.2.4節(jié))允許將字符串文字用作參數(shù)類型注釋中的類型。 字符串文字類型僅在該上下文中被允許,在其他地方則不允許。
所有字符串文字類型都是String基本類型的子類型。
TODO:擴展對字符串文字類型的支持。
3.3 Object類型
對象類型由屬性,調(diào)用簽名,構(gòu)造簽名和索引簽名(統(tǒng)稱為成員)組成。
類和接口類型的引用,數(shù)組類型,元組類型,函數(shù)類型和構(gòu)造函數(shù)類型都歸為對象類型。 TypeScript語言中的多個構(gòu)造可創(chuàng)建對象類型,包括:
- 對象類型文字(第3.8.3節(jié))。
- 數(shù)組類型文字(第3.8.4節(jié))。
- 元組類型文字(第3.8.5節(jié))。
- 函數(shù)類型文字(第3.8.8節(jié))。
- 構(gòu)造函數(shù)類型文字(第3.8.9節(jié))。
- 對象文字(第4.5節(jié))。
- 數(shù)組文字(第4.6節(jié))。
- 函數(shù)表達式(第4.10節(jié))和函數(shù)聲明(6.1)。
- 由類聲明創(chuàng)建的構(gòu)造函數(shù)類型(第8.2.5節(jié))。
- 由命名空間聲明創(chuàng)建的命名空間實例類型(第10.3節(jié))。
3.3.1 命名類型引用
對類和接口類型的類型引用(第3.8.2節(jié))被歸類為對象類型。 泛型類和接口類型的類型引用包括類型參數(shù),這些類型參數(shù)將替換類或接口的類型參數(shù)以產(chǎn)生實際的對象類型。
3.3.2 Array類型
數(shù)組類型表示具有常見元素類型的JavaScript數(shù)組。 數(shù)組類型是從全局命名空間中的通用接口類型“ Array”創(chuàng)建的命名類型引用,其中數(shù)組元素類型為類型實參。 數(shù)組類型文字(第3.8.4節(jié))提供了創(chuàng)建此類引用的簡寫符號。
“數(shù)組”接口的聲明包括屬性“長度”和元素類型的數(shù)字索引簽名,以及其他成員:
interface Array<T> { length: number; [x: number]: T; // Other members }數(shù)組文字(第4.6節(jié))可用于創(chuàng)建數(shù)組類型的值。 例如
var a: string[] = ["hello", "world"];如果類型可以分配給any []類型(第3.11.4節(jié)),則稱其為類似數(shù)組的類型。
3.3.3 Tuple類型
元組類型表示具有單獨跟蹤的元素類型的JavaScript數(shù)組。 元組類型使用元組類型文字(第3.8.5節(jié))編寫。 元組類型將一組數(shù)字命名的屬性與數(shù)組類型的成員結(jié)合在一起。 具體來說,元組類型
[ T0, T1, ..., Tn ]結(jié)合屬性集:
{ 0: T0; 1: T1; ... n: Tn; }元素類型為元組元素類型的并集類型(第3.4節(jié))的數(shù)組類型的成員。
數(shù)組文字(第4.6節(jié))可用于創(chuàng)建元組類型的值。 例如:
var t: [number, string] = [3, "three"]; var n = t[0]; // Type of n is number var s = t[1]; // Type of s is string var i: number; var x = t[i]; // Type of x is number | string可以通過聲明從Array 派生并引入數(shù)字命名屬性的接口來創(chuàng)建命名元組類型。 例如:
interface KeyValuePair<K, V> extends Array<K | V> { 0: K; 1: V; }var x: KeyValuePair<number, string> = [10, "ten"];如果類型具有數(shù)字名稱為“ 0”的屬性,則稱其為類似元組的類型。
3.3.4 Function類型
包含一個或多個調(diào)用簽名的對象類型稱為函數(shù)類型。 可以使用函數(shù)類型文字(第3.8.8節(jié))或通過在對象類型文字中包含調(diào)用簽名來編寫函數(shù)類型。
3.3.5 Constructor類型
包含一個或多個構(gòu)造簽名的對象類型被稱為構(gòu)造函數(shù)類型。 構(gòu)造函數(shù)類型可以使用構(gòu)造函數(shù)類型文字(第3.8.9節(jié))或在對象類型文字中包含構(gòu)造簽名來編寫。
3.3.6 Members
每個對象類型都由零個或多個以下類型的成員組成:
- 屬性,用于定義給定類型的對象的屬性的名稱和類型。 屬性名稱在其類型中是唯一的。
- 呼叫簽名,定義可能的參數(shù)列表和返回類型,這些類型與將呼叫操作應(yīng)用于給定類型的對象相關(guān)聯(lián)。
- 構(gòu)造簽名,用于定義可能的參數(shù)列表和返回類型,這些簽名和返回類型與將new運算符應(yīng)用于給定類型的對象有關(guān)。
- 索引簽名,用于定義給定類型的屬性的類型約束。 一個對象類型最多可以具有一個字符串索引簽名和一個數(shù)字索引簽名。
屬性是公共的,私有的或受保護的,并且是必需的或可選的:
- 類聲明中的屬性可以指定為公共,私有或受保護,而在其他上下文中聲明的屬性始終被視為公共。私有成員只能在其聲明的類中訪問,如第8.2.2節(jié)所述,私有屬性僅在子類型和分配兼容性檢查中與自身匹配,如第3.11節(jié)所述。受保護的成員只能在其聲明的類和從其派生的類中進行訪問,如第8.2.2節(jié)中所述,受保護的屬性僅與自身匹配,并在子類型和賦值兼容性檢查中覆蓋,如第3.11節(jié)中所述。
- 對象類型文字或接口聲明中的屬性可以指定為必需或可選,而在其他上下文中聲明的屬性始終被認為是必需的。如3.11.4節(jié)中所述,可以從源對象中忽略賦值的目標類型中可選的屬性。
通過包含帶有字符串文字類型的參數(shù),可以對調(diào)用和構(gòu)造簽名進行專門化(第3.9.2.4節(jié))。專用簽名用于表示模式,其中某些參數(shù)的特定字符串值導(dǎo)致其他參數(shù)的類型或函數(shù)結(jié)果變得更加專用。
3.4 Union類型
聯(lián)合類型表示可能具有幾種不同表示形式之一的值。 聯(lián)合類型A |的值。 B是A類型或B類型的值。聯(lián)合類型使用聯(lián)合類型文字(第3.8.6節(jié))編寫。
聯(lián)合類型包含一組有序的組成類型。 雖然通常是A | B等于B | 答:確定聯(lián)合類型的調(diào)用和構(gòu)造簽名時,構(gòu)成類型的順序可能很重要。
聯(lián)合類型具有以下子類型關(guān)系:
- 如果U中的每個類型都是T的子類型,則并集類型U是T的子類型。
- 如果T是U中任何類型的子類型,則類型T是聯(lián)合類型U的子類型。
同樣,聯(lián)合類型具有以下可分配性關(guān)系:
- 如果U中的每個類型都可以分配給T,則可以將聯(lián)合類型U分配給類型T。
- 如果T可分配給U中的任何類型,則類型T可分配給并集類型U。
|| 條件運算符(第4.19.7節(jié)和4.20節(jié))可能會產(chǎn)生聯(lián)合類型的值,而數(shù)組文字(第4.6節(jié))可能會產(chǎn)生以聯(lián)合類型作為其元素類型的數(shù)組值。
類型防護(第4.24節(jié))可用于將聯(lián)合類型縮小為更特定的類型。 特別是,類型防護對于將聯(lián)合類型值范圍縮小為非聯(lián)合類型值很有用。
在這個例子中
var x: string | number; var test: boolean; x = "hello"; // Ok x = 42; // Ok x = test; // Error, boolean not assignable x = test ? 5 : "five"; // Ok x = test ? 0 : false; // Error, number | boolean not assignable可以為’x’分配類型為字符串,數(shù)字或聯(lián)合類型字符串的值| 數(shù)字,但沒有其他任何類型。 要訪問“ x”中的值,可以使用類型保護將類型“ x”的類型首先縮小為字符串或數(shù)字:
var n = typeof x === "string" ? x.length : x; // Type of n is number出于屬性訪問和函數(shù)調(diào)用的目的,聯(lián)合類型的表觀成員(第3.11.1節(jié))是其每種構(gòu)成類型中都存在的成員,而類型是構(gòu)成類型中各個表觀成員的聯(lián)合。 以下示例說明了根據(jù)對象類型創(chuàng)建聯(lián)合類型時發(fā)生的成員類型合并。
interface A { a: string; b: number; }interface B { a: number; b: number; c: number; }var x: A | B; var a = x.a; // a has type string | number var b = x.b; // b has type number var c = x.c; // Error, no property c in union type請注意,“ xa”具有聯(lián)合類型,因為“ a”的類型在“ A”和“ B”中是不同的,而“ xb”只是具有類型號,因為這在“ A”和“ b”中都是“ b”的類型 ‘B’。 還要注意,沒有屬性“ x.c”,因為只有“ B”具有屬性“ c”。
當(dāng)用作上下文類型時(第4.23節(jié)),聯(lián)合類型具有那些以其任何構(gòu)成類型存在的成員,而這些類型是構(gòu)成類型中各個成員的聯(lián)合。 具體來說,用作上下文類型的并集類型具有第3.11.1節(jié)中定義的明顯成員,不同的是,特定成員僅需要以一種或多種構(gòu)成類型而不是所有構(gòu)成類型存在。
3.5 Intersection類型
交叉點類型表示同時具有多種類型的值。相交類型A和B的值是類型A和類型B的值。相交類型使用相交類型文字(第3.8.7節(jié))編寫。
交集類型包含一組有序的組成類型。雖然A和B等效于B&A通常是正確的,但是在確定調(diào)用和構(gòu)造交集類型的簽名時,構(gòu)成類型的順序可能很重要。
交叉點類型具有以下子類型關(guān)系:
- 如果I中的任何類型是T的子類型,則交集類型I是T的子類型。
- 如果T是I中每種類型的子類型,則類型T是交點類型I的子類型。
同樣,交叉點類型具有以下可分配性關(guān)系:
- 如果I中的任何類型都可以分配給T,則可以將交點類型I分配給類型T。
- 如果T可分配給I中的每個類型,則類型T可分配給相交類型I。
出于屬性訪問和函數(shù)調(diào)用的目的,交集類型的表觀成員(第3.11.1節(jié))是存在于其一個或多個組成類型中的那些成員,而類型是組成類型中各個表觀成員的交集。以下示例說明了根據(jù)對象類型創(chuàng)建交集類型時發(fā)生的成員類型合并。
interface A { a: number } interface B { b: number }var ab: A & B = { a: 1, b: 1 }; var a: A = ab; // A & B assignable to A var b: B = ab; // A & B assignable to Binterface X { p: A } interface Y { p: B }var xy: X & Y = { p: ab }; // X & Y has property p of type A & Btype F1 = (a: string, b: string) => void; type F2 = (a: number, b: number) => void;var f: F1 & F2 = (a: string | number, b: string | number) => { }; f("hello", "world"); // Ok f(1, 2); // Ok f(1, "test"); // Error聯(lián)合和交集類型運算符可以應(yīng)用于類型參數(shù)。 例如,此功能可用于對合并對象的函數(shù)進行建模:
function extend<T, U>(first: T, second: U): T & U { // Extend first with properties of second }var x = extend({ a: "hello" }, { b: 42 }); var s = x.a; var n = x.b;可以創(chuàng)建交集類型,對于這些交集類型,除null或undefined之外的其他值均不可能。 例如,基本類型(例如字符串和數(shù)字)的交集屬于此類別。
3.6 Type參數(shù)
類型參數(shù)表示在通用類型引用或通用函數(shù)調(diào)用中參數(shù)綁定到的實際類型。 類型參數(shù)具有約束條件,可為其實際類型參數(shù)建立上限。
由于類型參數(shù)表示大量不同的類型參數(shù),因此與其他類型相比,類型參數(shù)具有某些限制。 特別是,類型參數(shù)不能用作基類或接口。
3.6.1 Type Parameter列表
類,接口,類型別名和函數(shù)聲明可以選擇包含在<和>括號中的類型參數(shù)列表。對象,函數(shù)和構(gòu)造函數(shù)類型文字的調(diào)用簽名中還允許使用類型參數(shù)。
TypeParameters:<TypeParameterList>TypeParameterList:TypeParameterTypeParameterList,TypeParameterTypeParameter:BindingIdentifier Constraint(opt)Constraint:extends Type類型參數(shù)名稱必須唯一。如果同一TypeParameterList中的兩個或多個類型參數(shù)具有相同的名稱,則會發(fā)生編譯時錯誤。
類型參數(shù)的范圍擴展到與類型參數(shù)列表關(guān)聯(lián)的整個聲明,但類中的靜態(tài)成員聲明除外。
類型參數(shù)可能具有關(guān)聯(lián)的類型參數(shù)約束,該約束為類型實參建立上限。可以在同一類型參數(shù)列表內(nèi)的類型參數(shù)約束中引用類型參數(shù),甚至包括出現(xiàn)在類型參數(shù)左側(cè)的約束聲明。
類型參數(shù)T的基本約束定義如下:
- 如果T沒有聲明的約束,則T的基本約束為空對象類型{}。
- 如果T的聲明約束是類型參數(shù),則T的基本約束是該類型參數(shù)的約束。
- 否則,T的基本約束是T的聲明約束。
在這個例子中
interface G<T, U extends V, V extends Function> { }“ T”的基本約束是空對象類型,“ U”和“ V”的基本約束是“功能”。
為了確定類型關(guān)系(第3.11節(jié)),類型參數(shù)似乎是其基本約束的子類型。 同樣,在屬性訪問(第4.13節(jié)),新操作(第4.14節(jié))和函數(shù)調(diào)用(第4.15節(jié))中,類型參數(shù)似乎具有其基本約束的成員,但沒有其他成員。
類型參數(shù)直接或間接成為其自身的約束是錯誤的。 例如,以下兩個聲明均無效:
interface A<T extends T> { }interface B<T extends U, U extends T> { }3.6.2 Type Argument列表
泛型類型的類型引用(第3.8.2節(jié))必須包括用尖括號括起來并用逗號分隔的類型參數(shù)列表。 類似地,對泛型函數(shù)的調(diào)用(第4.15節(jié))可以顯式包括類型實參列表,而不是依賴于類型推斷。
TypeArguments:<?TypeArgumentList?> TypeArgumentList:TypeArgumentTypeArgumentList?,?TypeArgument TypeArgument:Type類型參數(shù)與所引用的泛型類型或函數(shù)的類型參數(shù)一一對應(yīng)。 需要一個類型實參列表為每個對應(yīng)的類型形參精確指定一個類型實參,并且需要一個約束類型形參的每個類型實參來滿足該類型形參的約束。 如果將類型實參替換為類型實參,則該類型實參滿足類型參數(shù)約束,則該類型實參可分配給約束類型(第3.11.4節(jié))。
給出聲明
interface G<T, U extends Function> { }類型為“ G <A,B>”的類型引用對“ A”沒有任何要求,但要求“ B”可分配給“功能”。
將類型實參替換為通用類型或通用簽名中的類型參數(shù)的過程稱為實例化通用類型或簽名。 如果提供的類型參數(shù)不滿足其對應(yīng)類型參數(shù)的約束,則泛型類型或簽名的實例化可能會失敗。
3.6.3 This類型
每個類和接口都有一個this類型,它表示類或接口的聲明中類或接口實例的實際類型。 在類型位置使用關(guān)鍵字this引用this-type。 在類的實例方法和構(gòu)造函數(shù)中,表達式this的類型(4.2節(jié))是類的this類型。
類和接口支持繼承,因此,在方法中由此方法表示的實例不一定是包含類的實例,實際上它可能是派生類或接口的實例。 為了對此關(guān)系建模,將類或接口的此類型分類為類型參數(shù)。 與其他類型參數(shù)不同,不可能為this-type顯式傳遞類型參數(shù)。 相反,在對類或接口類型的類型引用中,類型引用本身會隱式作為this-type的類型參數(shù)傳遞。 例如:
class A { foo() { return this; } }class B extends A { bar() { return this; } }let b: B; let x = b.foo().bar(); // Fluent pattern works, type of x is B在上面的b聲明中,類型引用B本身作為B的this-type的類型參數(shù)傳遞。 因此,引用的類型是類B的實例,其中所有該類型的實例都被B替換,因此,B的foo方法實際上返回B(與A相對)。
給定類或接口類型C的this-type隱含一個約束,該約束包括對C的類型引用,其中C自己的類型參數(shù)作為類型實參傳遞,并且該類型引用作為this-type的類型實參傳遞。
3.7 命名類型
類,接口,枚舉和類型別名是通過類聲明(第8.1節(jié)),接口聲明(第7.1節(jié)),枚舉聲明(9.1)和類型別名聲明(第3.10節(jié))引入的命名類型。類,接口和類型別名可以具有類型參數(shù),然后稱為泛型。相反,沒有類型參數(shù)的命名類型稱為非泛型類型。
接口聲明僅引入命名類型,而類聲明引入命名類型和構(gòu)造函數(shù),這些函數(shù)創(chuàng)建這些命名類型的實現(xiàn)實例。由類和接口聲明引入的命名類型只有細微的差別(類不能聲明可選成員,接口不能聲明私有或受保護的成員),并且在大多數(shù)情況下可以互換。特別是,僅具有公共成員的類聲明引入的命名類型的功能與接口聲明創(chuàng)建的命名類型完全相同。
命名類型通過類型引用(第3.8.2節(jié))進行引用,這些引用指定類型名稱,并在適用時指定要替換命名類型的類型參數(shù)的類型實參。
從技術(shù)上講,命名類型不是類型-僅引用命名類型。這種區(qū)別在泛型類型中尤為明顯:泛型類型是“模板”,可以通過編寫類型引用來從其創(chuàng)建多個實際類型,這些類型引用提供類型參數(shù)來代替泛型類型的類型參數(shù)。此替換過程稱為實例化泛型類型。只有實例化泛型類型后,它才表示實際類型。
TypeScript具有結(jié)構(gòu)類型系統(tǒng),因此,通用類型的實例與等效的手動擴展沒有區(qū)別。例如,給定聲明
interface Pair<T1, T2> { first: T1; second: T2; }類型參考:
Pair<string, Entity>與類型沒有區(qū)別:
{ first: string; second: Entity; }3.8 指定類型
通過引用其關(guān)鍵字或名稱或通過編寫對象類型文字,數(shù)組類型文字,元組類型文字,函數(shù)類型文字,構(gòu)造函數(shù)類型文字或類型查詢來指定類型。
Type:UnionOrIntersectionOrPrimaryTypeFunctionTypeConstructorTypeUnionOrIntersectionOrPrimaryType:UnionTypeIntersectionOrPrimaryTypeIntersectionOrPrimaryType:IntersectionTypePrimaryTypePrimaryType:ParenthesizedTypePredefinedTypeTypeReferenceObjectTypeArrayTypeTupleTypeTypeQueryThisType ParenthesizedType:(?Type?)當(dāng)聯(lián)合,交集,函數(shù)或構(gòu)造函數(shù)類型用作數(shù)組元素類型時,必須在它們之間加上括號; 交集類型中的聯(lián)合,函數(shù)或構(gòu)造函數(shù)類型周圍; 以及聯(lián)合類型中的函數(shù)或構(gòu)造函數(shù)類型。 例如:
(string | number)[] ((x: string) => string) | ((x: number) => number) (A | B) & (C | D)以下各節(jié)介紹了不同類型的類型符號。
3.8.1 預(yù)定義類型
any,number,boolean,string,symbol和void關(guān)鍵字分別引用Any類型和Number,Boolean,String,Symbol和Void基本類型。
PredefinedType:anynumberbooleanstringsymbolvoid預(yù)定義類型關(guān)鍵字是保留的,不能用作用戶定義類型的名稱。
3.8.2 類型引用
類型引用通過其名稱引用命名的類型或類型參數(shù),如果是通用類型,則提供類型參數(shù)列表。
TypeReference:TypeName?[no LineTerminator here]?TypeArgumentsoptTypeName:IdentifierReferenceNamespaceName?.?IdentifierReferenceNamespaceName:IdentifierReferenceNamespaceName?.?IdentifierReferenceTypeReference由TypeName組成,該TypeName引用命名的類型或類型參數(shù)。對泛型類型的引用之后必須是TypeArguments的列表(第3.6.2節(jié))。
TypeName是單個標識符或由點分隔的標識符序列。在類型名稱中,除最后一個標識符外,所有標識符均指命名空間,最后一個標識符指代命名類型。
在第2.4節(jié)中描述了由單個標識符組成的TypeName的解析。
解析形式為NX的TypeName,其中N為NamespaceName,X為IdentifierReference,首先解析命名空間名稱N。如果N的解析成功,并且導(dǎo)出成員集(第10.4和11.3.4.4節(jié))結(jié)果命名空間包含命名類型X,然后NX引用該成員。否則,N.X是不確定的。
由單個標識符組成的NamespaceName的解析在2.4節(jié)中描述。在命名空間聲明(第10.1節(jié))或?qū)肼暶?#xff08;第10.3、11.3.2和11.3.3節(jié))中聲明的標識符可以歸為命名空間。
解析形式為NX的NamespaceName,其中N為NamespaceName,X為IdentifierReference,首先解析命名空間名稱N。如果N的解析成功,并且導(dǎo)出成員集(第10.4和11.3.4.4節(jié))結(jié)果命名空間包含一個導(dǎo)出的命名空間成員X,然后NX引用該成員。否則,N.X是不確定的。
需要使用對通用類型的類型引用來為所引用的通用類型的每個類型參數(shù)精確指定一個類型參數(shù),并且每個類型參數(shù)必須可分配給(第3.11.4節(jié))相應(yīng)類型參數(shù)的約束,否則將產(chǎn)生錯誤發(fā)生。一個例子:
interface A { a: string; }interface B extends A { b: string; }interface C extends B { c: string; }interface G<T, U extends B> { x: T; y: U; }var v1: G<A, C>; // Ok var v2: G<{ a: string }, C>; // Ok, equivalent to G<A, C> var v3: G<A, A>; // Error, A not valid argument for U var v4: G<G<A, B>, C>; // Ok var v5: G<any, any>; // Ok var v6: G<any>; // Error, wrong number of arguments var v7: G; // Error, no arguments類型實參只是一個類型,本身可以是對通用類型的類型引用,如上例中的“ v4”所示。
如3.7節(jié)所述,對通用類型G的類型引用表示一種類型,其中G的所有類型參數(shù)的出現(xiàn)都已用類型引用中提供的實際類型自變量替換。 例如,上面的’v1’聲明等同于:
var v1: { x: { a: string; } y: { a: string; b: string; c: string }; };3.8.3 Object類型文法
對象類型文字通過指定靜態(tài)地認為在該類型的實例中存在的成員集來定義對象類型。 可以使用接口聲明為對象類型文字賦予名稱,但否則是匿名的。
ObjectType:{?TypeBodyopt?}TypeBody:TypeMemberList?;optTypeMemberList?,optTypeMemberList:TypeMemberTypeMemberList?;?TypeMemberTypeMemberList?,?TypeMemberTypeMember:PropertySignatureCallSignatureConstructSignatureIndexSignatureMethodSignature對象類型文字的成員被指定為屬性,調(diào)用,構(gòu)造,索引和方法簽名的組合。 對象類型成員在第3.9節(jié)中描述。
3.8.4 Array類型文法
數(shù)組類型文字被寫為元素類型,后跟一個打開和關(guān)閉的方括號。
ArrayType:PrimaryType?[no LineTerminator here]?[?]數(shù)組類型文字會引用具有給定元素類型的數(shù)組類型(第3.3.2節(jié))。 數(shù)組類型文字是在全局命名空間中引用通用接口類型“ Array”的簡寫形式,其中元素類型作為類型實參。
當(dāng)聯(lián)合,交集,函數(shù)或構(gòu)造函數(shù)類型用作數(shù)組元素類型時,必須將其括在括號中。 例如:
(string | number)[] (() => string)[]或者,可以使用“ Array ”符號來編寫數(shù)組類型。 例如,上述類型等同于
Array<string | number> Array<() => string>3.8.5 Tuple類型文法
元組類型文字是作為元素類型的序列編寫的,用逗號分隔并括在方括號中。
TupleType:[?TupleElementTypes?]TupleElementTypes:TupleElementTypeTupleElementTypes?,?TupleElementTypeTupleElementType:Type元組類型文字引用了元組類型(第3.3.3節(jié))。
3.8.6 Union類型文法
聯(lián)合類型文字被寫為由豎線分隔的一系列類型。
UnionType:UnionOrIntersectionOrPrimaryType | IntersectionOrPrimaryType聯(lián)合類型字面量引用聯(lián)合類型(第3.4節(jié))。
3.8.7 Intersection類型文法
交集類型文字被寫為由&分隔的一系列類型。
IntersectionType:IntersectionOrPrimaryType&PrimaryType交集類型文字會引用交集類型(第3.5節(jié))。
3.8.8 Function類型文法
函數(shù)類型文字可指定調(diào)用簽名的類型參數(shù),常規(guī)參數(shù)和返回類型。
FunctionType:TypeParametersopt(ParameterListopt)=> Type函數(shù)類型文字是包含單個調(diào)用簽名的對象類型的簡寫。 具體來說,是形式的函數(shù)類型文字
< T1, T2, ... > ( p1, p2, ... ) => R與對象類型文字完全等效
{ < T1, T2, ... > ( p1, p2, ... ) : R }請注意,具有多個調(diào)用或構(gòu)造簽名的函數(shù)類型不能寫為函數(shù)類型文字,而必須寫為對象類型文字。
3.8.9 Constructor類型文法
構(gòu)造函數(shù)類型文字可指定構(gòu)造簽名的類型參數(shù),常規(guī)參數(shù)和返回類型。
ConstructorType:new TypeParametersopt(ParameterListopt)=> Type構(gòu)造函數(shù)類型文字是包含單個構(gòu)造簽名的對象類型的簡寫。 具體來說,是以下形式的構(gòu)造函數(shù)類型文字
new < T1, T2, ... > ( p1, p2, ... ) => R與對象類型文字完全等效
{ new < T1, T2, ... > ( p1, p2, ... ) : R }請注意,具有多個構(gòu)造簽名的構(gòu)造函數(shù)類型不能寫為構(gòu)造函數(shù)類型文字,而必須寫為對象類型文字。
3.8.10 類型查詢
類型查詢獲取表達式的類型。
TypeQuery:typeof TypeQueryExpressionTypeQueryExpression:IdentifierReferenceTypeQueryExpression . Identifiername類型查詢由關(guān)鍵字typeof及其后的表達式組成。 該表達式僅限于單個標識符或由句點分隔的標識符序列。 該表達式被作為標識符表達式(第4.3節(jié))或?qū)傩栽L問表達式(第4.13節(jié))處理,其擴展類型(第3.12節(jié))成為結(jié)果。 與其他靜態(tài)類型構(gòu)造類似,類型查詢將從生成的JavaScript代碼中刪除,并且不增加運行時開銷。
類型查詢對于捕獲由各種構(gòu)造(例如對象文字,函數(shù)聲明和命名空間聲明)生成的匿名類型很有用。 例如:
var a = { x: 10, y: 20 }; var b: typeof a;上面的’b’與’a’具有相同的類型,即{x:number; y:數(shù)字; }。
如果聲明包含類型注釋,該注釋通過類型查詢的循環(huán)路徑或包含類型查詢的類型引用引用要聲明的實體,則結(jié)果類型為Any類型。 例如,以下所有變量的類型都為“任意”:
var c: typeof c; var d: typeof e; var e: typeof d; var f: Array<typeof f>;但是,如果類型查詢的循環(huán)路徑包括至少一個ObjectType,FunctionType或ConstructorType,則該構(gòu)造表示遞歸類型:
var g: { x: typeof g; }; var h: () => typeof h;這里,“ g”和“ g.x”具有相同的遞歸類型,同樣,“ h”和“ h()”具有相同的遞歸類型。
3.8.11 This類型推導(dǎo)
this關(guān)鍵字用于引用類或接口的this-type(第3.6.3節(jié))。
ThisType:thisThisType的含義取決于最接近的封閉函數(shù)FunctionDeclaration,FunctionExpression,PropertyDefinition,ClassElement或TypeMember,稱為ThisType的根聲明,如下所示:
- 當(dāng)根聲明是類的實例成員或構(gòu)造函數(shù)時,ThisType引用該類的this-type。
- 當(dāng)根聲明是接口類型的成員時,ThisType引用該接口的此類型。
- 否則,ThisType是錯誤。
注意,為了避免歧義,不可能在嵌套對象類型文字中引用此類的此類或接口。 在這個例子中
interface ListItem { getHead(): this; getTail(): this; getHeadAndTail(): { head: this, tail: this }; // Error }最后一行的this引用是錯誤的,因為其根聲明不是類或接口的成員。 在對象類型文字中引用外部類或接口的此類型的推薦方法是聲明中間泛型并將其作為類型參數(shù)傳遞。 例如:
type HeadAndTail<T> = { head: T, tail: T };interface ListItem { getHead(): this; getTail(): this; getHeadAndTail(): HeadAndTail<this>; }3.9 指定成員
對象類型文字(第3.8.3節(jié))的成員被指定為屬性,調(diào)用,構(gòu)造,索引和方法簽名的組合。
3.9.1 屬性簽名
屬性簽名聲明屬性成員的名稱和類型。
PropertySignature:PropertyName?opt TypeAnnotationoptTypeAnnotation::Type屬性簽名的PropertyName(2.2.2)在其包含類型內(nèi)必須是唯一的,并且如果它是計算所得的屬性名稱(2.2.3),則必須表示一個眾所周知的符號。 如果屬性名稱后面帶有問號,則該屬性為可選。 否則,該屬性是必需的。
如果屬性簽名省略了TypeAnnotation,則假定為Any類型。
3.9.2 Call簽名
呼叫簽名定義類型參數(shù),參數(shù)列表和返回類型,該類型參數(shù)與對包含類型的實例執(zhí)行呼叫操作(第4.15節(jié))相關(guān)。 通過定義多個不同的呼叫簽名,一種類型可能會使呼叫操作超載。
CallSignature:TypeParametersopt(ParameterListopt)TypeAnnotationopt包含TypeParameters(第3.6.1節(jié))的呼叫簽名稱為通用呼叫簽名。 相反,沒有TypeParameters的呼叫簽名稱為非通用呼叫簽名。
調(diào)用簽名不僅是對象類型文字的成員,還出現(xiàn)在方法簽名(第3.9.5節(jié)),函數(shù)表達式(第4.10節(jié))和函數(shù)聲明(第6.1節(jié))中。
包含調(diào)用簽名的對象類型被稱為函數(shù)類型。
3.9.2.1 Type參數(shù)
調(diào)用簽名中的類型參數(shù)(第3.6.1節(jié))提供了一種在調(diào)用操作中表達參數(shù)與返回類型之間關(guān)系的機制。例如,簽名可能會引入類型參數(shù),并將其用作參數(shù)類型和返回類型,實際上是描述一個函數(shù),該函數(shù)返回與其參數(shù)相同類型的值。
類型參數(shù)可以在引入它們的呼叫簽名的參數(shù)類型和返回類型注釋中引用,但不能在類型參數(shù)約束中引用。
用于呼叫簽名類型參數(shù)的類型參數(shù)(第3.6.2節(jié))可以在調(diào)用操作中明確指定,或者在可能的情況下,可以從調(diào)用中的常規(guī)參數(shù)的類型中推斷出類型參數(shù)(第4.15.2節(jié))。特定類型參數(shù)集的通用調(diào)用簽名的實例化是通過將每個類型參數(shù)替換為其對應(yīng)的類型參數(shù)而形成的調(diào)用簽名。
下面是帶有類型參數(shù)的呼叫簽名的一些示例。
一個函數(shù),它接受任何類型的參數(shù),并返回相同類型的值:
<T>(x: T): T該函數(shù)接受兩個相同類型的值,并返回該類型的數(shù)組:
<T>(x: T, y: T): T[]該函數(shù)接受兩個不同類型的參數(shù),并返回具有這些類型的屬性’x’和’y’的對象:
<T, U>(x: T, y: U): { x: T; y: U; }一個采用一個類型的數(shù)組和一個函數(shù)參數(shù)的函數(shù),返回另一種類型的數(shù)組,其中該函數(shù)參數(shù)采用第一個數(shù)組元素類型的值,并返回第二個數(shù)組元素類型的值:
<T, U>(a: T[], f: (x: T) => U): U[]3.9.2.2 參數(shù)列表
簽名的參數(shù)列表包含零個或多個必需參數(shù),然后是零個或多個可選參數(shù),最后是一個可選的rest參數(shù)。
ParameterList:RequiredParameterListOptionalParameterListRestParameterRequiredParameterList,OptionalParameterListRequiredParameterList,RestParameterOptionalParameterList,RestParameterRequiredParameterList,OptionalParameterList,RestParameterRequiredParameterList:RequiredParameterRequiredParameterList,RequiredParameterRequiredParameter:AccessibilityModifieropt BindingIdentifierOrPattern TypeAnnotationoptBindingIdentifier:StringLiteralAccessibilityModifier:publicprivateprotectedBindingIdentifierOrPattern:BindingIdentifierBindingPatternOptionalParameterList:OptionalParameterOptionalParameterList,OptionalParameterOptionalParameter:AccessibilityModifieropt BindingIdentifierOrPattern? TypeAnnotationoptAccessibilityModifieropt BindingIdentifierOrPatternTypeTypeAnnotationoptInitializerBindingIdentifier? : StringLiteralRestParameter:... BindingIdentifier TypeAnnotationopt參數(shù)聲明可以指定標識符或綁定模式(5.2.2)。參數(shù)聲明中指定的標識符和參數(shù)列表中的綁定模式在該參數(shù)列表中必須是唯一的。
簽名中參數(shù)的類型確定如下:
- 如果聲明中包含類型注釋,則參數(shù)為該類型。
- 否則,如果聲明包含初始化程序表達式(僅當(dāng)參數(shù)列表與函數(shù)體一起出現(xiàn)時才允許使用),則參數(shù)類型為初始化程序表達式類型的擴展形式(第3.12節(jié))。
- 否則,如果聲明指定了綁定模式,則參數(shù)類型是該綁定模式的隱含類型(第5.2.3節(jié))。
- 否則,如果參數(shù)是rest參數(shù),則參數(shù)類型為any []。
- 否則,參數(shù)類型為任何。
僅當(dāng)參數(shù)出現(xiàn)在ConstructorImplementation的參數(shù)列表(第8.3.1節(jié))中且未指定BindingPattern時,才允許其包含public,private或protected修飾符。
rest參數(shù)的類型注釋必須表示數(shù)組類型。
當(dāng)參數(shù)類型注釋指定字符串文字類型時,包含的簽名是專用簽名(第3.9.2.4節(jié))。不允許將專用簽名與函數(shù)體結(jié)合使用,即FunctionExpression,FunctionImplementation,MemberFunctionImplementation和ConstructorImplementation語法生成不允許使用字符串文字類型的參數(shù)。
可以通過在參數(shù)名稱或綁定模式后加上問號(?)或包含初始化程序來將參數(shù)標記為可選。僅當(dāng)參數(shù)列表與函數(shù)主體一起出現(xiàn)時才允許使用初始化程序(包括綁定屬性或元素初始化程序),即僅在FunctionExpression,FunctionImplementation,MemberFunctionImplementation或ConstructorImplementation語法生成中。
TODO:更新以反映綁定參數(shù)在實現(xiàn)簽名中不能為可選。
TODO:更新以反映必需的參數(shù)支持初始化程序。
3.9.2.3 Return類型
呼叫簽名的返回類型注釋(如果存在)指定由呼叫操作計算和返回的值的類型。 void返回類型注釋用于指示函數(shù)沒有返回值。
如果在沒有函數(shù)主體的上下文中發(fā)生沒有返回類型注釋的調(diào)用簽名,則假定返回類型為Any類型。
當(dāng)在具有函數(shù)主體(特別是函數(shù)實現(xiàn),成員函數(shù)實現(xiàn)或成員訪問器聲明)的上下文中發(fā)生沒有返回類型注釋的調(diào)用簽名時,將如本節(jié)所述從函數(shù)主體中推斷出返回類型。 6.3。
3.9.2.4 特定簽名
當(dāng)參數(shù)類型注釋指定字符串文字類型(第3.2.9節(jié))時,包含的簽名被視為專用簽名。 專用簽名用于表示模式,其中某些參數(shù)的特定字符串值會導(dǎo)致其他參數(shù)的類型或函數(shù)結(jié)果變得更加專用。 例如,聲明
interface Document { createElement(tagName: "div"): HTMLDivElement; createElement(tagName: "span"): HTMLSpanElement; createElement(tagName: "canvas"): HTMLCanvasElement; createElement(tagName: string): HTMLElement; }聲明使用字符串文字“ div”,“ span”和“ canvas”調(diào)用“ createElement”分別返回類型為“ HTMLDivElement”,“ HTMLSpanElement”和“ HTMLCanvasElement”的值,并使用所有其他字符串表達式返回“ HTMLElement”類型的值。
編寫上面的聲明之類的重載聲明時,最后列出非專用簽名非常重要。這是因為重載決議(第4.15.1節(jié))按聲明順序處理候選項,并選擇匹配的第一個候選項。
對象類型中的每個專用調(diào)用或構(gòu)造簽名必須至少可分配給同一對象類型中的至少一個非專用調(diào)用或構(gòu)造簽名(如果一個對象類型僅包含A,則認為一個調(diào)用簽名A可分配給另一個調(diào)用簽名B可分配給僅包含B)的對象類型。例如,上面示例中的’createElement’屬性的類型包含三個專用簽名,所有這些簽名都可以分配給該類型中的非專用簽名。
3.9.3 Construct簽名
構(gòu)造簽名定義了與將new運算符(第4.14節(jié))應(yīng)用于包含類型的實例相關(guān)聯(lián)的參數(shù)列表和返回類型。 通過定義具有不同參數(shù)列表的多個構(gòu)造簽名,類型可以使新操作過載。
ConstructSignature:new TypeParametersopt(ParameterListopt)TypeAnnotationopt構(gòu)造簽名的類型參數(shù),參數(shù)列表和返回類型應(yīng)遵循與調(diào)用簽名相同的規(guī)則。
包含構(gòu)造簽名的類型被稱為構(gòu)造函數(shù)類型。
3.9.4 索引簽名
索引簽名為包含類型中的屬性定義類型約束。
IndexSignature:[BindingIdentifier:string] TypeAnnotation[BindingIdentifier:number] TypeAnnotation索引簽名有兩種:
- 使用索引類型字符串指定的字符串索引簽名為所有屬性和包含類型中的數(shù)字索引簽名定義類型約束。具體地說,在類型為T的字符串索引簽名的類型中,所有屬性和數(shù)字索引簽名必須具有可分配給T的類型。
- 使用索引類型編號指定的數(shù)字索引簽名定義了包含類型中所有數(shù)字命名屬性的類型約束。具體地說,在具有數(shù)字類型T的數(shù)字索引簽名的類型中,所有以數(shù)字命名的屬性必須具有可分配給T的類型。
以數(shù)字命名的屬性是其名稱是有效數(shù)字文字的屬性。具體來說,名稱為N的屬性的ToString(ToNumber(N))與N相同,其中ToString和ToNumber是ECMAScript規(guī)范中定義的抽象操作。
一個對象類型最多可以包含一個字符串索引簽名和一個數(shù)字索引簽名。
索引簽名會影響對類型的確定,該確定是通過對包含類型的實例應(yīng)用括號表示法屬性訪問而產(chǎn)生的,如第4.13節(jié)所述。
3.9.5 方法簽名
方法簽名是用于聲明函數(shù)類型屬性的簡寫。
MethodSignature:PropertyName?opt CallSignature如果PropertyName是計算的屬性名稱(2.2.3),則必須指定一個眾所周知的符號。 如果PropertyName后面帶有問號,則該屬性為可選。 否則,該屬性是必需的。 僅對象類型文字和接口可以聲明可選屬性。
表單的方法簽名
f < T1, T2, ... > ( p1, p2, ... ) : R等同于屬性聲明
f : { < T1, T2, ... > ( p1, p2, ... ) : R }文字類型可以通過聲明多個具有相同名稱但參數(shù)列表不同的方法簽名來重載方法。 必須全部重載(省略問號),或者全部重載是可選的(包括問號)。 一組重載的方法簽名對應(yīng)于單個屬性的聲明,該聲明的類型由等效的一組調(diào)用簽名組成。 特別
f < T1, T2, ... > ( p1, p2, ... ) : R ; f < U1, U2, ... > ( q1, q2, ... ) : S ; ...相當(dāng)于
f : { < T1, T2, ... > ( p1, p2, ... ) : R ; < U1, U2, ... > ( q1, q2, ... ) : S ; ... } ;在下面的對象類型示例中
{ func1(x: number): number; // Method signature func2: (x: number) => number; // Function type literal func3: { (x: number): number }; // Object type literal }屬性“ func1”,“ func2”和“ func3”都是相同的類型,即具有單個調(diào)用簽名并帶有數(shù)字并返回數(shù)字的對象類型。 同樣,在對象類型中
{ func4(x: number): number; func4(s: string): string; func5: { (x: number): number; (s: string): string; }; }屬性“ func4”和“ func5”具有相同的類型,即具有兩個調(diào)用簽名的對象類型,分別帶有并返回數(shù)字和字符串。
3.10 類型別名
類型別名聲明在包含的聲明空間中引入了類型別名。
TypeAliasDeclaration:type BindingIdentifier TypeParametersopt = Type;類型別名用作類型別名聲明中指定的類型的別名。與總是引入命名對象類型的接口聲明不同,類型別名聲明可以為任何類型的類型引入名稱,包括基本類型,聯(lián)合類型和交集類型。
類型別名可以選擇具有類型參數(shù)(第3.6.1節(jié)),這些類型參數(shù)用作在類型引用中引用類型別名時要提供的實際類型的占位符。具有類型參數(shù)的類型別名稱為通用類型別名。通用類型別名聲明的類型參數(shù)在范圍內(nèi),并且可以在別名類型中引用。
使用類型引用(3.8.2)引用類型別名。對通用類型別名的類型引用使用給定的類型參數(shù)生成別名類型的實例化。編寫對非通用類型別名的引用與編寫別名類型本身具有完全相同的效果,而編寫對通用類型別名的引用與編寫別名類型的結(jié)果實例化具有完全相同的效果。
類型別名聲明的BindingIdentifier可能不是預(yù)定義的類型名稱之一(第3.8.1節(jié))。
類型別名中指定的類型依賴于該類型別名是錯誤的。類型具有以下依賴性:
- 類型別名直接取決于其別名的類型。
- 類型引用直接取決于所引用的類型以及每個類型參數(shù)(如果有)。
- 并集或交集類型直接取決于每種構(gòu)成類型。
- 數(shù)組類型直接取決于其元素類型。
- 元組類型直接取決于其每個元素類型。
- 類型查詢直接取決于引用實體的類型。
給定這個定義,一個類型所依賴的完整類型集就是直接依賴關(guān)系的傳遞閉包。請注意,對象類型文字,函數(shù)類型文字和構(gòu)造函數(shù)類型文字不依賴于其中引用的類型,因此允許通過類型別名循環(huán)引用自身。
類型別名聲明的一些示例:
type StringOrNumber = string | number; type Text = string | { text: string }; type NameLookup = Dictionary<string, Person>; type ObjectStatics = typeof Object; type Callback<T> = (data: T) => void; type Pair<T> = [T, T]; type Coordinates = Pair<number>; type Tree<T> = T | { left: Tree<T>, right: Tree<T> };接口類型與對象類型文字的類型別名有很多相似之處,但是由于接口類型提供了更多的功能,因此它們通常比類型別名更可取。 例如,接口類型
interface Point { x: number; y: number; }可以寫為類型別名
type Point = { x: number; y: number; };但是,這樣做意味著失去了以下功能:
- 可以在extend或Implements子句中命名接口,但是不能為對象類型文字提供類型別名。
- 接口可以具有多個合并的聲明,但是對象類型文字的類型別名不能。
3.11 Type關(guān)系
TypeScript中的類型具有身份,子類型,超類型和分配兼容性關(guān)系,如以下各節(jié)所定義。
3.11.1 明顯成員
類型的表觀成員是在子類型,超類型和分配兼容性關(guān)系以及屬性訪問(4.13節(jié)),新操作(4.14節(jié))和函數(shù)調(diào)用(4.15節(jié))的類型檢查中觀察到的成員。類型的外觀成員確定如下:
- 基本類型Number和所有枚舉類型的明顯成員是全局接口類型’Number’的明顯成員。
- 基本類型布爾值的表觀成員是全局接口類型“布爾值”的表觀成員。
- 基本類型String和所有字符串文字類型的明顯成員是全局接口類型’String’的明顯成員。
- 類型參數(shù)的表觀成員是該類型參數(shù)的約束的表觀成員(第3.6.1節(jié))。
- 對象類型T的表觀成員是以下各項的組合:
- T的已聲明和/或繼承的成員。
- 全局接口類型“對象”的屬性不會被T中具有相同名稱的屬性隱藏。
- 如果T具有一個或多個調(diào)用或構(gòu)造簽名,則全局接口類型’Function’的屬性不會被T中具有相同名稱的屬性隱藏。
- 聯(lián)合類型U的表觀成員確定如下:
- 當(dāng)U的所有構(gòu)成類型都具有名為N的外觀屬性時,U會具有各自屬性類型的并集類型的外觀屬性N。
- 當(dāng)U的所有組成類型均具有帶有參數(shù)列表P的明顯呼叫簽名時,U具有帶有參數(shù)列表P和作為各自返回類型的并集的返回類型的明顯呼叫簽名。呼叫簽名以與第一種構(gòu)成類型相同的順序出現(xiàn)。
- 當(dāng)U的所有構(gòu)成類型均具有帶有參數(shù)列表P的明顯構(gòu)造體簽名時,U具有帶有參數(shù)列表P的明顯構(gòu)造體簽名以及作為各個返回類型的并集的返回類型。構(gòu)造簽名的出現(xiàn)順序與第一種組成類型相同。
- 當(dāng)U的所有構(gòu)成類型均具有表觀字符串索引簽名時,U具有各自字符串索引簽名類型的并集類型的表觀字符串索引簽名。
- 當(dāng)U的所有構(gòu)成類型均具有表觀數(shù)字索引簽名時,U具有各自數(shù)字索引簽名類型的并集類型的表觀數(shù)字索引簽名。
- 相交類型I的外觀成員確定如下:
- 當(dāng)I的多個構(gòu)成類型之一具有名為N的外觀屬性時,我具有相應(yīng)屬性類型的交集類型的名為N的外觀屬性。
- 當(dāng)I的一個或多個組成類型具有呼叫簽名S時,I則具有明顯的呼叫簽名S。這些簽名按I中組成類型的順序按每個組成類型的簽名的順序進行排序。
- 當(dāng)I的一個或多個構(gòu)成類型具有構(gòu)造簽名S時,我具有明顯的構(gòu)造簽名S。這些簽名按I中構(gòu)成類型的順序按每種構(gòu)成類型的簽名的順序排列。
- 當(dāng)I的一種或多種組成類型具有明顯的字符串索引簽名時,我具??有相應(yīng)的字符串索引簽名類型的交集類型的明顯的字符串索引簽名。
- 當(dāng)我的一個或多個構(gòu)成類型具有明顯的數(shù)字索引簽名時,我具??有相應(yīng)的數(shù)字索引簽名類型的交集類型的明顯的數(shù)字索引簽名。
如果類型不是上述之一,則認為它沒有明顯的成員。
實際上,類型的外觀成員使其成為“對象”或“功能”接口的子類型,除非該類型定義的成員與“對象”或“功能”接口的成員不兼容(例如,如果type定義的屬性與“ Object”或“ Function”接口中的屬性同名,但其類型不是“ Object”或“ Function”接口中的子類型。
一些例子:
var o: Object = { x: 10, y: 20 }; // Ok var f: Function = (x: number) => x * x; // Ok var err: Object = { toString: 0 }; // Error最后一個賦值是一個錯誤,因為對象文字的’toString’方法與’Object’的方法不兼容。
3.11.2 Type和Member類型
兩種類型被認為是相同的
- 它們都是Any類型,
- 它們是相同的原始類型,
- 它們是相同的類型參數(shù)
- 它們是具有相同構(gòu)成類型集的聯(lián)合類型,或者
- 它們是具有相同構(gòu)成類型集的交集類型,或者
- 它們是具有相同成員集的對象類型。
當(dāng)兩個成員被認為相同時
- 它們是具有相同名稱,可選性和類型的公共屬性,
- 它們是源自同一聲明且具有相同類型的私有或受保護屬性,
- 它們是相同的呼叫簽名
- 它們是相同的構(gòu)造簽名,或者
- 它們是具有相同類型,相同類型的索引簽名。
當(dāng)兩個調(diào)用或構(gòu)造簽名具有相同數(shù)量的類型參數(shù)且具有相同類型參數(shù)約束時,并且在用type Any替換簽名所引入的類型參數(shù)之后,將相同數(shù)量的相同類型參數(shù)(必需,可選或其余)視為相同)和類型,以及相同的返回類型。
請注意,除了具有私有或受保護成員的原始類型和類之外,確定身份的是結(jié)構(gòu)的類型而非命名。另外,請注意,在確定簽名身份時,參數(shù)名稱并不重要。
僅當(dāng)私有屬性和受保護屬性起源于相同的聲明并且具有相同的類型時,它們才匹配。如果兩個不同的類型是對同一泛型類的單獨參數(shù)化引用,則兩個不同的類型可能包含源自同一聲明的屬性。在這個例子中
class C<T> { private x: T; }interface X { f(): string; }interface Y { f(): string; }var a: C<X>; var b: C<Y>;變量’a’和’b’具有相同的類型,因為對C的兩個類型引用都創(chuàng)建了具有源自同一聲明的私有成員’x’的類型,并且因為兩個私有’x’成員具有 類型參數(shù)“ X”和“ Y”被替換后,成員將完全相同。
3.11.3 子類型和超類型
如果S不具有相對于T的多余屬性(3.11.5),并且滿足以下條件之一,則S是T類型的子類型,并且T是S的超類型。
- S和T是相同的類型。
- T是Any類型。
- S是未定義的類型。
- S是Null類型,T不是Undefined類型。
- S是枚舉類型,T是原始類型Number。
- S是字符串文字類型,而T是原始類型String。
- S是聯(lián)合類型,S的每個構(gòu)成類型是T的子類型。
- S是交集類型,S的至少一個組成類型是T的子類型。
- T是并集類型,S是T的至少一個組成類型的子類型。
- T是交集類型,S是T的每個組成類型的子類型。
- S是類型參數(shù),S的約束是T的子類型。
- S是對象類型,交集類型,枚舉類型或Number,Boolean或String基本類型,T是對象類型,并且對于T中的每個成員M,下列條件之一為真:
- M是一個屬性,S是一個明顯的屬性N,其中
- M和N具有相同的名稱,
- N的類型是M的子類型,
- 如果M是必需屬性,則N也是必需屬性,并且
- M和N都是公共的,M和N都是私有的,并且起源于同一聲明,M和N都受保護,起源于同一聲明,或者M受保護,并且N聲明于從該類繼承的類中M被聲明。
- M是非專業(yè)的調(diào)用或構(gòu)造簽名,S是明顯的調(diào)用或構(gòu)造簽名N,其中,當(dāng)使用類型Any作為M和N聲明的所有類型參數(shù)(如果有)的類型實參來實例化M和N時,
- 簽名屬于同一種類(調(diào)用或構(gòu)造),
- M具有一個休息參數(shù),或者N中非可選參數(shù)的數(shù)量小于或等于M中的參數(shù)總數(shù),
- 對于兩個簽名中都存在的參數(shù)位置,N中的每個參數(shù)類型都是M中相應(yīng)參數(shù)類型的子類型或超類型,并且
- M的結(jié)果類型是Void,或者N的結(jié)果類型是M的子類型。
- M是類型U的字符串索引簽名,而U是Any類型,或者S具有明顯類型的字符串索引簽名,該類型是U的子類型。
- M是類型U的數(shù)字索引簽名,U是Any類型,或者S具有作為U的子類型的類型的表觀字符串或數(shù)字索引簽名。
- M是一個屬性,S是一個明顯的屬性N,其中
比較調(diào)用或構(gòu)造簽名時,參數(shù)名稱將被忽略,其余參數(shù)對應(yīng)于其余參數(shù)元素類型的可選參數(shù)的無限制擴展。
注意,在確定子類型和超類型關(guān)系時,專用的調(diào)用和構(gòu)造簽名(第3.9.2.4節(jié))并不重要。
另請注意,類型參數(shù)不被視為對象類型。因此,類型參數(shù)T的唯一子類型是T本身以及直接或間接約束為T的其他類型參數(shù)。
3.11.4 賦值兼容性
在某些情況下,類型必須與賦值兼容,例如賦值語句中的表達式和變量類型以及函數(shù)調(diào)用中的參數(shù)和參數(shù)類型。
如果S相對于T(3.11.5)沒有多余的屬性并且滿足以下條件之一,則S可分配給T類型,T可從S分配給T:
- S和T是相同的類型。
- S或T是Any類型。
- S是未定義的類型。
- S是Null類型,T不是Undefined類型。
- S或T是枚舉類型,另一個是原始類型Number。
- S是字符串文字類型,而T是原始類型String。
- S是聯(lián)合類型,并且S的每個組成類型都可以分配給T。
- S是交叉點類型,并且S的至少一個組成類型可分配給T。
- T是聯(lián)合類型,并且S可分配給T的至少一個組成類型。
- T是交集類型,并且S可分配給T的每個組成類型。
- S是類型參數(shù),并且S的約束可分配給T。
- S是對象類型,交集類型,枚舉類型或Number,Boolean或String基本類型,T是對象類型,并且對于T中的每個成員M,下列條件之一為真:
- M是一個屬性,S是一個明顯的屬性N,其中
- M和N具有相同的名稱,
- N的類型可分配給M的類型,
- 如果M是必需屬性,則N也是必需屬性,并且
- M和N都是公共的,M和N都是私有的,并且起源于同一聲明,M和N都受保護,起源于同一聲明,或者M受保護,并且N聲明于從該類繼承的類中M被聲明。
- M是可選屬性,S沒有與M相同名稱的明顯屬性。
- M是非專業(yè)的調(diào)用或構(gòu)造簽名,S是明顯的調(diào)用或構(gòu)造簽名N,其中,當(dāng)使用類型Any作為M和N聲明的所有類型參數(shù)(如果有)的類型實參來實例化M和N時,
- 簽名屬于同一種類(調(diào)用或構(gòu)造),
- M具有一個休息參數(shù),或者N中非可選參數(shù)的數(shù)量小于或等于M中的參數(shù)總數(shù),
- 對于兩個簽名中都存在的參數(shù)位置,N中的每個參數(shù)類型都可以分配給M中的相應(yīng)參數(shù)類型或從M中的相應(yīng)參數(shù)類型分配,并且
- M的結(jié)果類型為Void或N的結(jié)果類型可分配給M的結(jié)果類型。
- M是類型U的字符串索引簽名,而U是Any類型,或者S具有可分配給U的類型的表觀字符串索引簽名。
- M是類型U的數(shù)字索引簽名,而U是Any類型,或者S具有可分配給U的明顯的字符串或數(shù)字索引簽名。
- M是一個屬性,S是一個明顯的屬性N,其中
比較調(diào)用或構(gòu)造簽名時,參數(shù)名稱將被忽略,其余參數(shù)對應(yīng)于其余參數(shù)元素類型的可選參數(shù)的無限制擴展。
注意,在確定分配兼容性時,專用的調(diào)用和構(gòu)造簽名(第3.9.2.4節(jié))并不重要。
分配兼容性和子類型化規(guī)則的不同之處僅在于:
- 任何類型均可分配給所有類型,但不能分配給所有類型,
- 基本類型Number可以分配給所有枚舉類型,但不能為其子類型,并且
- 沒有特定屬性的對象類型可以分配給該屬性是可選的對象類型。
分配兼容性規(guī)則意味著,在分配值或傳遞參數(shù)時,可選屬性必須要么存在且具有兼容類型,要么根本不存在。例如:
function foo(x: { id: number; name?: string; }) { }foo({ id: 1234 }); // Ok foo({ id: 1234, name: "hello" }); // Ok foo({ id: 1234, name: false }); // Error, name of wrong type foo({ name: "hello" }); // Error, id required but missing3.11.5 額外屬性
子類型和分配兼容性關(guān)系要求源類型相對于其目標類型沒有多余的屬性。此檢查的目的是檢測對象文字中過多或拼寫錯誤的屬性。
如果滿足以下條件,則認為源類型S相對于目標類型T具有多余的屬性
- S是如下定義的新鮮對象文字類型,并且
- S具有T中不期望的一個或多個屬性。
如果滿足以下條件之一,則可以認為類型T是期望的屬性P:
- T不是對象,并集或交集類型。
- T是對象類型,并且
- T具有與P同名的屬性,
- T具有字符串或數(shù)字索引簽名,
- T沒有屬性,或者
- T是全局類型“對象”。
- T是聯(lián)合或交集類型,并且在T的至少一種構(gòu)成類型中期望P。
為對象文字推斷的類型(如第4.5節(jié)中所述)被認為是新鮮的對象文字類型。當(dāng)對象文字類型被擴展(3.12)或類型斷言中的表達式類型(4.16)時,新鮮度消失。
考慮以下示例:
interface CompilerOptions { strict?: boolean; sourcePath?: string; targetPath?: string; }var options: CompilerOptions = { strict: true, sourcepath: "./src", // Error, excess or misspelled property targetpath: "./bin" // Error, excess or misspelled property };'CompilerOptions’類型僅包含可選屬性,因此,無需檢查多余的屬性,任何對象文字都可以分配給’options’變量(因為拼寫錯誤的屬性將被視為其他名稱的多余屬性)。
如果期望有多余的屬性,則可以將索引簽名添加到目標類型以指示意圖:
interface InputElement { name: string; visible?: boolean; [x: string]: any; // Allow additional properties of any type }var address: InputElement = { name: "Address", visible: true, help: "Enter address here", // Allowed because of index signature shortcut: "Alt-A" // Allowed because of index signature };3.11.6 上下文簽名實例化
在函數(shù)調(diào)用中進行類型實參推斷期間(第4.15.2節(jié)),在某些情況下,有必要在參數(shù)的非泛型調(diào)用簽名的上下文中實例化實參表達式的泛型調(diào)用簽名,以便可以進行進一步的推斷。 。 在非通用呼叫簽名B的上下文中實例化通用呼叫簽名A,如下所示:
- 使用3.11.7中描述的過程,針對兩個簽名中存在的那些參數(shù)位置,從B中的每個參數(shù)類型到A中的對應(yīng)參數(shù)類型,推導(dǎo)A的類型參數(shù),其中其余參數(shù)對應(yīng)于可選參數(shù)的無窮擴展 其余參數(shù)元素類型的所有參數(shù)。
- 每個類型參數(shù)的推斷類型參數(shù)是對該類型參數(shù)進行的推理的并集類型。 但是,如果聯(lián)合類型不滿足type參數(shù)的約束,則推斷的type參數(shù)將成為約束。
3.11.7 類型推導(dǎo)
在某些情況下,對給定類型參數(shù)集的推斷是從一個類型S(在其中不出現(xiàn)這些類型參數(shù))到另一個類型T(在其中發(fā)生這些類型參數(shù))進行的。推論包括為每個類型參數(shù)收集的一組候選類型參數(shù)。推理過程將S和T遞歸關(guān)聯(lián),以收集盡可能多的推理:
- 如果T是對其進行推斷的類型參數(shù)之一,則將S添加到該類型參數(shù)的推斷集合中。
- 否則,如果S和T是對相同泛型的引用,則從S中的每個類型實參到T中的每個對應(yīng)的類型實參進行推斷。
- 否則,如果S和T是元素數(shù)相同的元組類型,則從S中的每個元素類型到T中的每個對應(yīng)元素類型進行推斷。
- 否則,如果T是聯(lián)合或相交類型:
- 首先,從S到T中的每個組成類型進行推斷,這不僅僅是簡單地對其進行推斷的類型參數(shù)之一。
- 如果第一步?jīng)]有產(chǎn)生推論,則如果T是聯(lián)合類型,并且T中恰好一個構(gòu)成類型只是對其進行推論的類型參數(shù),則從S對該類型參數(shù)進行推論。
- 否則,如果S是聯(lián)合或交集類型,則從S到T中的每個組成類型進行推斷。
- 否則,如果S和T是對象類型,則對于T中的每個成員M:
- 如果M是一個屬性,并且S包含與M同名的屬性N,則從N的類型到M的類型進行推斷。
- 如果M是呼叫簽名,并且S中存在對應(yīng)的呼叫簽名N,則將Any類型實例化為每個類型參數(shù)(如果有)的參數(shù),并從N中的參數(shù)類型推斷出 M中的對應(yīng)參數(shù)類型對于兩個簽名中都存在的位置,以及從N的返回類型到M的返回類型。
- 如果M是結(jié)構(gòu)簽名,并且S中存在對應(yīng)的結(jié)構(gòu)簽名N,則將Any類型實例化為每個類型參數(shù)(如果有)的參數(shù),并從N中的參數(shù)類型推導(dǎo)到M中的對應(yīng)參數(shù)類型對于兩個簽名中都存在的位置,以及從N的返回類型到M的返回類型。
- 如果M是字符串索引簽名,而S包含字符串索引簽名N,則從N的類型到M的類型進行推斷。
- 如果M是數(shù)字索引簽名,并且S包含數(shù)字索引簽名N,則從N的類型到M的類型進行推斷。
- 如果M是數(shù)字索引簽名,并且S包含字符串索引簽名N,則從N的類型到M的類型進行推斷。
比較調(diào)用或構(gòu)造簽名時,S中的簽名按聲明順序成對地按T配對成相同類型的簽名。如果S和T在給定類型的簽名中具有不同的編號,則將忽略較長列表的聲明順序中多余的第一個簽名。
TODO:更新以反映改進的聯(lián)合和相交類型推斷。
3.11.8 遞歸類型
類和接口可以在其內(nèi)部結(jié)構(gòu)中引用自己,從而有效地創(chuàng)建具有無限嵌套的遞歸類型。 例如,類型
interface A { next: A; }包含“下一個”屬性的無限嵌套序列。 這樣的類型是完全有效的,但是在確定類型關(guān)系時需要特殊對待。 具體來說,當(dāng)比較給定關(guān)系(身份,子類型或可分配性)的類型S和T時,假定所討論的關(guān)系對于相同S和T的每個直接或間接嵌套出現(xiàn)都是正確的(其中,相同意味著 在相同的聲明中,并且(如果適用)具有相同的類型參數(shù))。 例如,考慮上面的“ A”和下面的“ B”之間的身份關(guān)系:
interface B { next: C; }interface C { next: D; }interface D { next: B; }為了確定“ A”和“ B”是否相同,首先比較“ A”和“ C”類型的“下一個”屬性。 這導(dǎo)致比較類型“ A”和“ D”的“下一個”屬性,從而導(dǎo)致比較類型“ A”和“ B”的“下一個”屬性。 由于已經(jīng)比較了“ A”和“ B”,因此根據(jù)定義,這種關(guān)系是正確的。 這進而導(dǎo)致其他比較為真,因此最終結(jié)果為真。
當(dāng)使用相同的技術(shù)比較泛型類型引用時,兩個類型引用源自相同的聲明并且具有相同的類型參數(shù),則它們被認為是相同的。
在某些情況下,以遞歸方式直接或間接引用自身的泛型類型可能會導(dǎo)致無數(shù)種不同的實例化。 例如,在類型
interface List<T> { data: T; next: List<T>; owner: List<List<T>>; }'List '具有類型’List <List >‘的成員’所有者’,其成員具有’List <List <List >>‘類型的成員’所有者’ 類型為“列表<列表<列表<列表<列表>>>”的“所有者”,依此類推,是無限的。 由于類型關(guān)系是從結(jié)構(gòu)上確定的,可能會探究組成類型的全部深度,因此,為了確定涉及無限擴展泛型類型的類型關(guān)系,編譯器可能有必要在某個點終止遞歸,并假設(shè)不會進行進一步探索 改變結(jié)果。
3.12 加寬類型
在某些情況下,TypeScript從上下文推斷類型,從而減輕了程序員顯式指定明顯類型的需求。 例如
var name = "Steve";將“名稱”的類型推斷為String基本類型,因為這是用于初始化它的值的類型。 從表達式中推斷變量,屬性或函數(shù)的類型時,源類型的擴展形式將用作目標的推斷類型。 類型的加寬形式是將所有出現(xiàn)的Null和Undefined類型替換為any類型的類型。
以下示例顯示了擴展類型以產(chǎn)生推斷的變量類型的結(jié)果。
var a = null; // var a: any var b = undefined; // var b: any var c = { x: 0, y: null }; // var c: { x: number, y: any } var d = [ null, undefined ]; // var d: any[]總結(jié)
以上是生活随笔為你收集整理的[TypeScript] 编程实践之1: Google的TypeScript代码风格3:类型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 励志
- 下一篇: 朋友圈发圈助手文案,头像,壁纸组合微信小