跳到主要內容
黯羽輕揚每天積累一點點

基本型別_TypeScript 筆記 2

免費2019-01-12#TypeScript#TypeScript变量类型#TypeScript教程#TypeScript数组类型#TypeScript修改window#TypeScript修改global

13 種基本型別

一. JavaScript 型別

JavaScript 有 7 種型別:Boolean、Number、String、Undefined、Null、Object,以及 ES6 新增的 Symbol

這 7 種 TypeScript 全都支援:

// JavaScript支持的7种类型
let isDone: boolean = false;  // 布尔值
let decimal: number = 6;      // 数值
let color: string = 'blue';   // 字符串
let u: undefined = undefined; // Undefined
let n: null = null;           // Null
let obj: object = {};         // Object
let sym: symbol = Symbol();   // Symbol

變數宣告

上面範例中的變數都是透過 let 宣告的,其實有 3 種變數宣告方式:

  • var:函式作用域

  • let:區塊級作用域

  • const:區塊級作用域,常數(不允許修改)

例如:

var a: string = 'a';
let b: string = 'b';
const c: string = 'c';

與 JavaScript 變數宣告方式完全一致,不再贅述,具體見 Variable Declarations

P.S. 實際上, letconst 最終都會被編譯成 var ,區塊級作用域等特性透過變數重新命名來模擬

二. TypeScript 型別

TypeScript 共有 13 種基本型別,除了 JavaScript 所有的 7 種之外,還有:

  • Array:陣列,表示一組型別相同的元素

  • Tuple:元組,表示一組固定數量的元素(不要求型別相同),如二元組、三元組

  • Enum:列舉,常數集合

  • Any:任意型別,表示未知型別,比如動態內容(使用者輸入、或第三方類別庫)或不知道型別的東西(混合型別陣列),可以宣告 any 型別繞過型別檢查

  • Void:空型別,表示沒有型別,比如無回傳值函式的回傳值型別

  • Never:絕不存在的值的型別,如永遠不會回傳的函式(必定拋異常的,或函式體有死迴圈的)的回傳值型別

範例如下:

// TypeScript新增的6种类型
let list: number[] = [1, 2, 3];       // 数组
let list: Array<number> = [1, 2, 3];  // 数组
let x: [string, number] = ["hello", 10];        // 元组
enum Color {Red = 'r', Green = 'g', Blue = 'b'} // 枚举
let notSure: any = 4;                 // 任意类型
let list: any[] = [1, true, "free"];  // 任意类型数组(未知类型)
function warnUser(): void {/*..*/}              // 空类型
function neverReturn(): never {throw 'error';}  // 绝不存在的类型

需要注意幾點:

  • Array 型別有 2 種宣告格式( elemType []Array<elemType>

  • 存取 Tuple 發生越界時,套用聯合型別(union type),所以上例中 x[10] 的型別是 string | number

  • Enum 值可以省略,預設按 key 宣告順序從 0 開始。如果指定了數值,後一項的值在此基礎上遞增,否則要求之後的項都要指定值(預設的數值遞增機制應付不了了)

  • Any 型別相當於局部的型別檢查開關,這在 TypeScript 與 JavaScript 程式碼並存的專案中很有意義

  • Void 型別的變數也是合法的,約束值只能是 undefinednull

  • Null、Undefined 和 Never 是其他型別的子型別,因此可以賦值給任何其他型別變數(例如 let str: string = null 也是合法的)

  • 其他任何型別都不可以賦值給 Never 型別,即便是 Any 也不行

  • Never 型別的變數也是合法的,此時 Never 可以用作型別保護(例如 declare const name: never; 避免隱式存取 window.name

P.S. 特殊的,建議開啟 --strictNullChecks 選項,此時 UndefinedNull 只允許賦值給 Void 以及各自對應的型別

P.S. 關於 Never 作為型別保護的應用,見 Improve type safety of name global variable

三. 型別斷言

可以透過型別斷言告知 TypeScript 編譯器某個值的確切型別:

Type assertions are a way to tell the compiler “trust me, I know what I’m doing.”

類似於其他語言裡的強制型別轉換(type casting),區別在於型別斷言只是編譯時的,不像型別轉換一樣具有執行時影響:

A type assertion is like a type cast in other languages, but performs no special checking or restructuring of data. It has no runtime impact, and is used purely by the compiler.

有兩種語法格式,分別是 <type>as type ,例如

let someValue: any = "this is a string";
// <type>
let strLength: number = (<string>someValue).length;
// as type
let strLength: number = (someValue as string).length;

兩種方式等效,但在 JSX 中只能用 as type (角括號語法與 JSX 語法衝突)

四. 常用技巧

存取列舉 key

實際上, TypeScript 列舉型別建立了 key-value 的雙向索引,例如:

enum Color {Red = 1, Green, Blue}
// 对应的JavaScript为
var Color;
(function (Color) {
    Color[Color["Red"] = 1] = "Red";
    Color[Color["Green"] = 2] = "Green";
    Color[Color["Blue"] = 3] = "Blue";
})(Color || (Color = {}));
// 得到
// {1: "Red", 2: "Green", 3: "Blue", Red: 1, Green: 2, Blue: 3}

因此,一個有意思的技巧是根據列舉值存取 key

let colorName: string = Color[2];
// 此时,colorName为'Green'

修改 global

Any 型別用來繞過編譯時型別檢查,因此可以用來修改一些不能改的東西,例如:

window.customFunction = myCustomFunction;

編譯報錯:

Property 'customFunction' does not exist on type 'Window'.

可以透過 any 型別繞過:

const globalAny: any = window;
globalAny.customFunction = myCustomFunction;

或者等效的型別斷言:

(<any> window).customFunction = myCustomFunction;
// 或
(window as any).customFunction = myCustomFunction;

參考資料

評論

暫無評論,快來發表你的看法吧

提交評論