為了使程式有用,我們需要能夠處理一些最簡單的資料單元:數字、字串、結構體、布林值等等。在 TypeScript 中,我們支援與 JavaScript 中預期的相同的型別,並額外增加了一個列舉型別來幫助處理相關問題。
布林值 (Boolean)
最基本的資料型別是簡單的 true/false 值,JavaScript 和 TypeScript 稱之為 boolean 值。
tsTryletisDone : boolean = false;
數字 (Number)
與 JavaScript 一樣,TypeScript 中的所有數字要麼是浮點數值,要麼是 BigIntegers。這些浮點數型別為 number,而 BigIntegers 型別為 bigint。除了十六進位制和十進位制字面量外,TypeScript 還支援 ECMAScript 2015 中引入的二進位制和八進位制字面量。
tsTryletdecimal : number = 6;lethex : number = 0xf00d;letbinary : number = 0b1010;letoctal : number = 0o744;letbig : bigint = 100n;
字串 (String)
無論是在網頁還是伺服器上建立 JavaScript 程式,另一個基礎部分是處理文字資料。與其他語言一樣,我們使用 string 型別來表示這些文字資料型別。就像 JavaScript 一樣,TypeScript 也使用雙引號 (") 或單引號 (') 來包裹字串資料。
tsTryletcolor : string = "blue";color = 'red';
你還可以使用 模板字串,它可以跨越多行幷包含嵌入的表示式。這些字串用反引號/反單引號 (`) 字元包裹,嵌入的表示式形式為 ${ expr }。
tsTryletfullName : string = `Bob Bobbington`;letage : number = 37;letsentence : string = `Hello, my name is ${fullName }.I'll be ${age + 1} years old next month.`;
這等同於如下宣告 sentence
tsTryletsentence : string ="Hello, my name is " +fullName +".\n\n" +"I'll be " +(age + 1) +" years old next month.";
陣列 (Array)
TypeScript 和 JavaScript 一樣,允許你操作值陣列。陣列型別可以透過兩種方式之一編寫。第一種方式是使用元素型別後跟 [] 來表示該元素型別的陣列
tsTryletlist : number[] = [1, 2, 3];
第二種方式使用泛型陣列型別,Array<elemType>
tsTryletlist :Array <number> = [1, 2, 3];
元組 (Tuple)
元組型別允許你表示一個已知元素數量和型別的陣列,且各元素的型別不必相同。例如,你可能想表示一個由 string 和 number 組成的對
tsTry// Declare a tuple typeletx : [string, number];// Initialize itx = ["hello", 10]; // OK// Initialize it incorrectlyType 'number' is not assignable to type 'string'.x = [10 ,"hello" ]; // Error
Type 'string' is not assignable to type 'number'.2322
2322Type 'number' is not assignable to type 'string'.
Type 'string' is not assignable to type 'number'.
當使用已知索引訪問元素時,會得到正確的型別
tsTry// OKconsole .log (x [0].substring (1));Property 'substring' does not exist on type 'number'.2339Property 'substring' does not exist on type 'number'.console .log (x [1].(1)); substring
訪問已知索引集之外的元素會導致錯誤
tsTryTuple type '[string, number]' of length '2' has no element at index '3'.2493Tuple type '[string, number]' of length '2' has no element at index '3'.x [3 ] = "world";Object is possibly 'undefined'.console .log (x [5 ].toString ());
Tuple type '[string, number]' of length '2' has no element at index '5'.2532
2493Object is possibly 'undefined'.
Tuple type '[string, number]' of length '2' has no element at index '5'.
列舉 (Enum)
對 JavaScript 標準資料型別集合的一個有益補充是 enum。正如 C# 等語言一樣,列舉是一種為一組數值賦予更友好名稱的方法。
tsTryenumColor {Red ,Green ,Blue ,}letc :Color =Color .Green ;
預設情況下,列舉從 0 開始為成員編號。你可以透過手動設定其中一個成員的值來更改此設定。例如,我們可以將前面的例子從 1 而不是 0 開始
tsTryenumColor {Red = 1,Green ,Blue ,}letc :Color =Color .Green ;
或者,甚至可以手動設定列舉中的所有值
tsTryenumColor {Red = 1,Green = 2,Blue = 4,}letc :Color =Color .Green ;
列舉的一個便捷功能是,你還可以從數值獲取列舉中的名稱。例如,如果我們有值 2 但不確定它在上面的 Color 列舉中對應什麼,我們可以查詢相應的名稱
tsTryenumColor {Red = 1,Green ,Blue ,}letcolorName : string =Color [2];// Displays 'Green'console .log (colorName );
未知 (Unknown)
在編寫應用程式時,我們可能需要描述那些我們尚不知道型別的變數。這些值可能來自動態內容——例如來自使用者——或者我們可能有意在 API 中接受所有值。在這些情況下,我們需要提供一個型別,告訴編譯器和未來的讀者此變數可以是任何內容,因此我們給它 unknown 型別。
tsTryletnotSure : unknown = 4;notSure = "maybe a string instead";// OK, definitely a booleannotSure = false;
如果你有一個型別為 unknown 的變數,你可以透過進行 typeof 檢查、比較檢查或其他稍後章節將討論的高階型別守衛來將其縮小為更具體的型別
tsTrydeclare constmaybe : unknown;// 'maybe' could be a string, object, boolean, undefined, or other typesconstType 'unknown' is not assignable to type 'number'.2322Type 'unknown' is not assignable to type 'number'.: number = aNumber maybe ;if (maybe === true) {// TypeScript knows that maybe is a boolean nowconstaBoolean : boolean =maybe ;// So, it cannot be a stringconstType 'boolean' is not assignable to type 'string'.2322Type 'boolean' is not assignable to type 'string'.: string = aString maybe ;}if (typeofmaybe === "string") {// TypeScript knows that maybe is a stringconstaString : string =maybe ;// So, it cannot be a booleanconstType 'string' is not assignable to type 'boolean'.2322Type 'string' is not assignable to type 'boolean'.: boolean = aBoolean maybe ;}
任意 (Any)
在某些情況下,並非所有的型別資訊都是可用的,或者宣告這些型別需要花費不合理的精力。這種情況可能出現在來自非 TypeScript 編寫的程式碼或第三方庫的值中。在這些情況下,我們可能希望放棄型別檢查。為此,我們使用 any 型別來標註這些值
tsTrydeclare functiongetValue (key : string): any;// OK, return value of 'getValue' is not checkedconststr : string =getValue ("myString");
any 型別是一種強大的處理現有 JavaScript 的方法,允許你在編譯期間逐步開啟或關閉型別檢查。
與 unknown 不同,any 型別的變數允許你訪問任意屬性,即使是那些不存在的屬性。這些屬性包括函式,TypeScript 不會檢查它們的存在或型別
tsTryletlooselyTyped : any = 4;// OK, ifItExists might exist at runtimelooselyTyped .ifItExists ();// OK, toFixed exists (but the compiler doesn't check)looselyTyped .toFixed ();letstrictlyTyped : unknown = 4;'strictlyTyped' is of type 'unknown'.18046'strictlyTyped' is of type 'unknown'.. strictlyTyped toFixed ();
any 將會繼續透過你的物件進行傳播
tsTryletlooselyTyped : any = {};letd =looselyTyped .a .b .c .d ;
最後,請記住 any 的所有便利都是以犧牲型別安全性為代價的。型別安全是使用 TypeScript 的主要動機之一,你應該儘量避免在不必要時使用 any。
空值 (Void)
void 有點像 any 的反面:表示完全沒有任何型別。你通常會看到它作為不返回任何值的函式的返回型別
tsTryfunctionwarnUser (): void {console .log ("This is my warning message");}
宣告 void 型別的變數並沒有什麼用,因為你只能將 null(僅在未指定 strictNullChecks 時,見下一節)或 undefined 賦值給它們
tsTryletunusable : void =undefined ;// OK if `--strictNullChecks` is not givenunusable = null;
Null 和 Undefined
在 TypeScript 中,undefined 和 null 實際上分別有它們自己的型別名:undefined 和 null。就像 void 一樣,它們單獨使用時並不是很有用
tsTry// Not much else we can assign to these variables!letu : undefined =undefined ;letn : null = null;
預設情況下,null 和 undefined 是所有其他型別的子型別。這意味著你可以將 null 和 undefined 賦值給類似 number 的型別。
但是,當使用 strictNullChecks 標記時,null 和 undefined 只能賦值給 unknown、any 和它們各自的型別(唯一的例外是 undefined 也可以賦值給 void)。這有助於避免許多常見的錯誤。如果你想傳入 string、null 或 undefined,可以使用聯合型別 string | null | undefined。
聯合型別是一個高階主題,我們將在稍後的章節中介紹。
注意:我們鼓勵在可能的情況下使用
strictNullChecks,但為了本手冊的目的,我們將假設它是關閉的。
Never (從不)
never 型別表示永遠不會發生的值型別。例如,never 是那些總是丟擲異常或從不返回的函式表示式或箭頭函式表示式的返回型別。當被永遠不可能為真的型別守衛縮小範圍時,變數也會獲得 never 型別。
never 型別是每種型別的子型別,並可以賦值給每種型別;然而,沒有型別是 never 的子型別,也沒有型別可以賦值給 never(除了 never 本身)。即使 any 也不能賦值給 never。
一些返回 never 的函式示例
tsTry// Function returning never must not have a reachable end pointfunctionerror (message : string): never {throw newError (message );}// Inferred return type is neverfunctionfail () {returnerror ("Something failed");}// Function returning never must not have a reachable end pointfunctioninfiniteLoop (): never {while (true) {}}
物件 (Object)
object 是表示非原始型別的型別,即除了 number、string、boolean、bigint、symbol、null 或 undefined 之外的任何型別。
使用 object 型別,可以更好地表示像 Object.create 這樣的 API。例如
tsTrydeclare functioncreate (o : object | null): void;// OKcreate ({prop : 0 });create (null);Argument of type 'undefined' is not assignable to parameter of type 'object | null'.2345Argument of type 'undefined' is not assignable to parameter of type 'object | null'.create (); // with `--strictNullChecks` flag enabled, undefined is not a subtype of null undefined Argument of type 'number' is not assignable to parameter of type 'object'.2345Argument of type 'number' is not assignable to parameter of type 'object'.create (42 );Argument of type 'string' is not assignable to parameter of type 'object'.2345Argument of type 'string' is not assignable to parameter of type 'object'.create ("string" );Argument of type 'boolean' is not assignable to parameter of type 'object'.2345Argument of type 'boolean' is not assignable to parameter of type 'object'.create (false );
通常,你不需要使用它。
型別斷言 (Type assertions)
有時你會陷入一種情況,你對一個值的瞭解比 TypeScript 多。通常這種情況發生在你意識到某個實體的型別可能比其當前型別更具體時。
型別斷言是一種告訴編譯器“相信我,我知道我在做什麼”的方法。型別斷言類似於其他語言中的型別轉換,但它不執行任何特殊的檢查或資料重構。它對執行時沒有任何影響,純粹由編譯器使用。TypeScript 假定作為程式設計師的你已經執行了所需的任何特殊檢查。
型別斷言有兩種形式。
一種是 as 語法
tsTryletsomeValue : unknown = "this is a string";letstrLength : number = (someValue as string).length ;
另一種版本是“尖括號”語法
tsTryletsomeValue : unknown = "this is a string";letstrLength : number = (<string>someValue ).length ;
這兩個樣本是等效的。使用哪一種主要取決於個人偏好;然而,當在 JSX 中使用 TypeScript 時,只允許使用 as 風格的斷言。
關於 let 的說明
你可能已經注意到,到目前為止,我們一直使用 let 關鍵字而不是你可能更熟悉的 JavaScript 的 var 關鍵字。let 關鍵字實際上是 TypeScript 提供的一種較新的 JavaScript 構造。你可以在手冊參考中閱讀關於 變數宣告 的內容,瞭解 let 和 const 如何修復 var 的許多問題。
關於 Number、String、Boolean、Symbol 和 Object
人們很容易認為 Number、String、Boolean、Symbol 或 Object 型別與上面推薦的小寫版本相同。然而,這些型別並不指代語言原語,且幾乎永遠不應該被用作型別。
tsTryfunctionreverse (s :String ):String {returns .split ("").reverse ().join ("");}reverse ("hello world");
相反,請使用 number、string、boolean、object 和 symbol 型別。
tsTryfunctionreverse (s : string): string {returns .split ("").reverse ().join ("");}reverse ("hello world");