探索 TypeScript 類型註解 - 內置類型

Exploring TypeScript Type Annotations - Built-in Typesgit

關於github

本文由 WowBar 團隊首發於 GitHubjson

做者: zhilidali數組

歡迎來到 《探索 TypeScript 類型註解》 系列教程。 開篇咱們(從新)認識了 TypeScript,本篇探索 TypeScript 的內置類型。函數

目錄

  1. 使用類型註解
  2. 基礎類型
  3. 引用類型

正文ui

1 使用類型註解

let foo = 'TS';
let bar: boolean = foo; // Error: Type 'string' is not assignable to type 'boolean'.ts(2322)
複製代碼

類型註解

Type Annotationsthis

語法: type。如 :booleanspa

做用 :約定變量的數據類型。如約定 bar 爲布爾值。rest

好處code

  1. 靜態編譯時檢查類型。如編譯器會警告 Type 'string' is not assignable to type 'boolean'
  2. 做爲文檔。在 VSCode 中將光標移到第二行 bar 上,會提示 let foo: string

類型推論

Type Inference

foo 的類型沒有顯示指定,TypeScript 會根據上下文自行推斷。 let foo = 'TS';let foo: string = TS; 是等價的。

2 基礎類型

Primitive Type

  • 支持 booleannumberstringsymbolundefinednull 基礎類型
  • 新增 voidnever 基礎類型
  • 新增 any 類型

JS 基礎類型

TypeScript 支持 JavaScript 的基礎類型

let tsBoo: boolean = false;
let tsNum: number = 0x10;
let tsStr: string = 'ts';
let tsSym: symbol = Symbol('ts');
let tsUnInit: undefined;
let tsEmpty: null = null;
複製代碼

TS 還支持基本包裝類型 BooleanNumberStringSymbol,基本類型爲基本包裝類型的子類型。

// 基本包裝類型 Boolean
let tsBool1: Boolean = new Boolean();
// 基本類型爲基本包裝類型的子類型
let tsBool2: Boolean = false;
複製代碼

新增基礎類型

void

  • void 標識函數沒有返回值(返回 undefined)。
function tsVoid(): void {
	// 沒有 return,即 `return undefined` 時使用
}
複製代碼

void VS. undefined

  • 在 JS 中,void 爲操做符,總返回 undefined; 而 undefined 在寬鬆模式下,可做變量。
  • 在 TS 中,void 做爲返回值類型時,可用其餘類型替換,而 undefined 不行。
function bar(callback: () => void) {}
function baz(callback: () => undefined) {}
// foo 返回 number 類型
function foo(): number { return 1; }

bar(foo); // foo 返回的 number 類型替換爲 void 類型
baz(foo); // Error:`Type 'number' is not assignable to type 'undefined'.(2345)`)
複製代碼

never

  • never 標識函數不會 return。如拋出異常或生成器函數存在 while(true){}
  • never 是全部類型的子類型,可賦給任意類型。
function tsNever1(): never {
	throw new Error('Throw Exception or never return');
}
function *tsNever2(): never {
	while(true) {
		// ...
	}
}
複製代碼

基礎類型兼容

never

前面說過,never 是全部類型的子類型。在 tsconfig.json 中:

  • strictNullChecks 爲 false 時,可直接賦給任意類型。
  • strictNullChecks 爲 true 時,never 需在賦值後才能使用。
let tsNever: never;
let tsNum: number;
let f = function():never {throw 'never'};

tsNum = tsNever; // `strictNullChecks` 爲 true 時,提示 Error。
tsNever = f();
tsNum = tsNever;
複製代碼

any

TS 還增長了 any 類型,當不但願 TS 檢查時使用。

  • 任意類型賦值給 any 類型或 any 類型賦值給任意類型 (never 除外) 均不會報錯。 any
let tsAny: any = 'any value';
let tsNum: number = tsAny; // 可賦值給任意類型
tsAny = true; // 可被賦值任意類型
複製代碼

undefined && null

undefinednull 爲子類型。在 tsconfig.json 中:

  • strictNullChecks 爲 false 時,undefined、null 可賦值給除never 外的任意類型的變量。
  • strictNullChecks 爲 true 時,undefined 只能賦值給 voidany 類型的變量。
let tsNum: number = undefined;
let tsVoid: void = undefined;
複製代碼

3 引用類型

Reference Type

  • 支持 Object、Array、Date、RegExp、Error、Function、Class 等類型
  • 新增 Tuple、Enum 類型

Object

object 描述(只讀)對象類型

let tsObj1: object = { a: 1 };
tsObj1.x = 2; // Error: Property 'x' does not exist on type 'object'.
複製代碼

Array

三種定義方式(後兩種詳見下篇):

  1. 類型後加 [],即 T[]
  2. Array Generic 數組泛型Array<T> ReadonlyArray<T>
  3. Number Index Signature 數值索引簽名 : 經過 interface 定義類型
let tsArr1: string[] = ['foo'];

// 數組泛型
let tsArr2: Array<string> = ['foo'];
let readonlyArr: ReadonlyArray<string> = ['foo']; // 只讀數組

// 數值索引簽名
interface IdxType { [index: number]: string }
let tsArr3: IdxType = ['foo'];
複製代碼

Tuple

元組:已知元素數量和類型的數組

let tsTuple: [string, number] ;

tsTuple = ['foo', 1];
tsTuple = [1, 'foo']; // Error

tsTuple[0].toUpperCase();
tsTuple[1].toUpperCase(); // Error

// 訪問越界元素時會使用聯合類型: (string | number)
tsTuple[2] = 'bar';
tsTuple[2] = 2;
tsTuple[2] = false; // Error
複製代碼

Enum

枚舉: 定義一組命名常量(枚舉成員只讀)

  1. Numeric enums 數值枚舉 : 可定義初始值(默認爲 0),後面根據初始值遞增。
  2. String enums 字符串枚舉
  3. Heterogeneous enums 異構枚舉
// Numeric enums
enum Color { Red = 2, Green, Blue };
/* 編譯器反向映射爲 var Color; (function(Color) { Color[(Color["Red"] = 2)] = "Red"; Color[(Color["Green"] = 3)] = "Green"; Color[(Color["Blue"] = 4)] = "Blue"; })(Color || (Color = {})); */
let num: Color = Color.Green; // 3
let str: string = Color[3]; // Green

// String enums
enum Response { No = 'NO', Yes = 'YES' }

// Heterogeneous enums
enum HeterogeneousEnum { No = 0, Yes = "YES" }
複製代碼

Date RegExp Error

let date: Date = new Date();
let reg: RegExp = /\.ts$/;
let err: Error = new Error('error');
複製代碼

Function

描述參數和返回值類型

  • (paramter: T): U 描述函數定義
  • : (paramter: T) => U 描述函數變量
// 函數聲明
function fn1(s: string): string {
	return s;
}
// 箭頭函數表達式
let fn2 = (s: string): string => s;

// 函數變量 fn
let fn3: (str: string) => string = fn2;
複製代碼

參數

  • optional parameters 可選參數 : foo?: T
  • default parameters 默認參數 : foo: T = value
  • rest parameter 剩餘參數 : ...rest: T[]
let fn2 = (
	s: string, // 必選參數
	b: string = '', // 默認參數
	c?: string, // 可選參數;位於必選參數後面
	...d: string[] // 剩餘參數;位於參數最後
): string => s;
複製代碼

重載

// Overload
function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {
	if (typeof x === 'number') {
		return Number(x.toString().split('').reverse().join(''));
	} else if (typeof x === 'string') {
		return x.split('').reverse().join('');
	}
}
複製代碼

Class

TS 保留並增添了功能 (目前 TS 與 ES 的類表現不一致)

ES :

class F {
	constructor(msg) {
		this.foo = msg;
	}
	getFoo() {
		return this.foo;
	}
}

class B extends F {
	constructor(msg) {
		super(msg);
	}
	getFoo() {
		return 'b' + super.getFoo();
	}
}
複製代碼

TS :

class F {
	foo: string
	constructor(msg: string) {
		this.foo = msg;
	}
	getFoo() {
		return this.foo;
	}
}

class B extends F {
	constructor(msg: string) {
		super(msg);
	}
	getFoo() {
		return 'b' + super.getFoo();
	}
}
複製代碼

結語 本篇介紹了 TS 的內置類型,下一篇介紹如何自定義類型。

CC BY-NC-ND 4.0
LICENSE

本做品採用知識共享署名-非商業性使用-禁止演繹 4.0 國際許可協議進行許可。

相關文章
相關標籤/搜索