注意,數(shù)據(jù)類(lèi)型大小寫(xiě)不同。如Boolean是構(gòu)造函數(shù)而boolean是基本類(lèi)型,如Object包含數(shù)組,而object不包含。
類(lèi)型兼容
在TS符合鴨子類(lèi)型,只要兩個(gè)類(lèi)型內(nèi)部結(jié)構(gòu)相同即兼容
類(lèi)型注解
聲明變量時(shí)若沒(méi)有設(shè)置類(lèi)型和初始值,則類(lèi)型為any,初始值為undefined。
聲明變量若指定了初始值但沒(méi)有指定類(lèi)型,則觸發(fā)類(lèi)型推論,自動(dòng)附加類(lèi)型。
基本類(lèi)型
- boolean
- number
- string
-
undefined 和 null
兩者各自有自己的類(lèi)型分別叫做undefined和null。
未開(kāi)啟--strictNullChecks時(shí),null和undefined是所有類(lèi)型的子類(lèi)型,例如可以把null賦值給number類(lèi)型的變量。 - void
方法無(wú)返回,或return無(wú)值,或return undefined
object
所有非基本類(lèi)型的父集
declare function create(o: object | null): void;
create({ prop: 0 }); // OK
create(null); // OK
create(42); // Error
create(undefined); // Error
數(shù)組
- 類(lèi)型+括號(hào)表示法
let a: number[] = [1, 2, 3];
let c: (number | string)[] = [1, 2, "3"];
let d: number[][] = [[1,2],[3,4]];
- 數(shù)組泛型
Array<>
let b: Array<number | string> = [1, 2, "3"];
- 用接口表示數(shù)組
通常僅用于類(lèi)數(shù)組對(duì)象,如以下IArguments是內(nèi)置接口
// interface IArguments {
// [index: number]: any;
// length: number;
// callee: Function;
// }
function sum() {
let args: IArguments = arguments;
}
元組(元素?cái)?shù)量和類(lèi)型固定的數(shù)組)
當(dāng)訪問(wèn)一個(gè)越界的元素,會(huì)使用聯(lián)合類(lèi)型替代
let x: [string, number];
x = ['hello', 10];
x[3] = 'world'; // OK, 字符串可以賦值給(string | number)類(lèi)型
any
聲明變量時(shí)若沒(méi)有設(shè)置類(lèi)型和初始值,則類(lèi)型為any,初始值為undefined。
any類(lèi)型會(huì)跳過(guò)編譯階段的類(lèi)型檢查,可以任意賦值或調(diào)用屬性,不建議使用。
let something: any;
something = 'seven';
something = 7;
something.setName('Tom');
unknown
安全版的any,任何類(lèi)型都能分配給unknown,而unknown只能分配給unknown、any或者未聲明類(lèi)型。
unknow類(lèi)型必須類(lèi)型斷言轉(zhuǎn)化為其他類(lèi)型后才能操作,彌補(bǔ)了any的缺點(diǎn)。
let c: unknown = 100;
c+=10;//Object is of type 'unknown'
(c as number) += 10;
(<number>c) += 10;
let d = c as number;
never
方法不會(huì)執(zhí)行完(拋出異?;驘o(wú)限循環(huán))
never可以被賦值給任何類(lèi)型,但任何類(lèi)型都不能賦值給never
// 返回值為 never 的函數(shù)可以是無(wú)法被執(zhí)行到的終止點(diǎn)的情況
function loop(): never {
while (true) {}
}
let x: never;
// 運(yùn)行錯(cuò)誤,數(shù)字類(lèi)型不能轉(zhuǎn)為 never 類(lèi)型
x = 123;
// 運(yùn)行正確,never 類(lèi)型可以賦值給 never類(lèi)型
x = (()=>{ throw new Error('exception')})();
聯(lián)合類(lèi)型
滿足其中一種類(lèi)型即可賦值
但后續(xù)只能訪問(wèn)此聯(lián)合類(lèi)型中所有類(lèi)型共有的屬性或方法:
function fn(x: boolean | string):void{
console.log(x.length);//error boolean上不存在屬性length
}
字面量類(lèi)型
直接將字面量作為一個(gè)類(lèi)型,通常配合聯(lián)合類(lèi)型使用可起到類(lèi)似枚舉的作用
let num: 1 | 2 | 3 = 1;
let str: "a" | "b" | "c" = c;
類(lèi)型推論
如聲明變量時(shí),指定了初始值但沒(méi)有指定類(lèi)型,則觸發(fā)類(lèi)型推論,自動(dòng)附加類(lèi)型。
如既沒(méi)有初始值又沒(méi)有指定類(lèi)型,則推斷為any。
let num = 'seven';
num = "7";
num = 7;//error TS2322: Type 'number' is not assignable to type 'string'.
let num2;
num2 = 'seven';
num2 = 7;
類(lèi)型斷言(建議只變?yōu)楦?xì),不要變?yōu)楦:?/h5>
可通過(guò)值 as 類(lèi)型或<類(lèi)型>值進(jìn)行斷言,不建議使用后者,因容易與泛型混淆。
類(lèi)型斷言只會(huì)影響 TypeScript 編譯時(shí)的類(lèi)型,類(lèi)型斷言語(yǔ)句在編譯結(jié)果中會(huì)被刪除。
通常用于為any、unknow、聯(lián)合類(lèi)型、外部傳入內(nèi)容、父類(lèi)對(duì)象等,指定更精確的數(shù)據(jù)類(lèi)型。當(dāng)斷言為更模糊的數(shù)據(jù)類(lèi)型時(shí)要慎用,因等同于繞過(guò)了編譯器的類(lèi)型檢查,可能會(huì)造成運(yùn)行時(shí)錯(cuò)誤。
let a:number = 666;
let aLength1 = a.length;//報(bào)錯(cuò) 類(lèi)型number不存在屬性length
let aLength2 = (a as any).length;//不報(bào)錯(cuò)
通過(guò)雙重?cái)嘌?/strong>甚至可以將一個(gè)類(lèi)型先斷言為any,再斷言為任一其他類(lèi)型。
let a:string = "hello";
(a as any as number) = 100;
類(lèi)型聲明比類(lèi)型斷言更嚴(yán)謹(jǐn),因類(lèi)型不會(huì)變更模糊:
interface Animal {
name: string;
}
interface Cat {
name: string;
run(): void;
}
const animal: Animal = {
name: 'tom'
};
不報(bào)錯(cuò) 鴨子類(lèi)型,雖然沒(méi)有使用 interface Cat extends Animal,依然視為兼容
let fake_tom = animal as Cat;
報(bào)錯(cuò)
let real_tom: Cat = animal;
類(lèi)型別名 type
使用type關(guān)鍵字定義數(shù)據(jù)類(lèi)型,方便對(duì)數(shù)據(jù)類(lèi)型進(jìn)行管理和復(fù)用
//字面量類(lèi)型
let num_1:1|2|3 = 1;
type Num_123 = 1 | 2 | 3;
let num_2: Num_123 = 1;
//元組
let tuple_1: [string, number] = ["1", 1];
type Tuple = [string, number];
let tuple_2: Tuple = ["1", 1];
interface IContact {
name: string; // 姓名
phone?: number; // 手機(jī)號(hào)
email: string; // 郵箱
avatar: string; // 頭像
}
type Contact = IContact
- Omit 用于去除類(lèi)型中某些字段
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
type OmitContact = Omit<Contact, 'email' | 'avatar'>;
const obj_omit: OmitContact = {
name: "vv"
};
- Pick 用于只保留類(lèi)型中某些字段
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
type PickContact = Pick<Contact, 'name' | 'phone'>;
const obj_pick: PickContact = {
name: "vv"
};
- Partial 用于把類(lèi)型中所有字段變?yōu)榭蛇x
type Partial<T> = {
[P in keyof T]?: T[P];
};
type PartialContact = Partial<Contact>;
const obj_partial: PartialContact = {};
- Required 用于把類(lèi)型中所有字段變?yōu)楸剡x
type Required<T> = {
[P in keyof T]-?: T[P];
};
type RequiredContact = Required<Contact>;
const obj_required: RequiredContact = {
name: "vv",
phone: 111,
email: "123@qq.com",
avatar: "XXX"
};
- 也可以自行創(chuàng)建一個(gè)類(lèi)型,如添加字段:
type WithId<T, P = number> = T & { id: P; };
type ContactWithId = WithId<PickContact>;
const obj_with_id: ContactWithId = {
name: "vv",
id: 1
};
枚舉 enum
- 數(shù)字枚舉
默認(rèn)從0依次遞增,也可以自己設(shè)置
可以用key取value,也可以用value取key
enum Color {Red = 1, Green, Blue};
var c: Color = Color.Green;//2
var c2: string= Color[2];//"Green"
//事實(shí)上此時(shí)對(duì)應(yīng)的js為:
//Color[Color["Green"] = 2] = "Green";
//即Color.Green為2,且Color[2]為'Green'
- 字符串枚舉
只能用key取value
enum Color {Red = "red", Sat = <any>"S"};
var c:Color = Color["Red"];
接口 interface
接口是對(duì)行為的抽象,而具體如何行動(dòng)需要由類(lèi)去實(shí)現(xiàn)(implement)。此外,接口也可用于對(duì)象形狀的描述。在TS中,其類(lèi)型檢查符合“鴨式辨型法”也稱(chēng)做“結(jié)構(gòu)性子類(lèi)型化”。
因接口是類(lèi)型而非真正的值,在編譯結(jié)果中會(huì)被刪除,無(wú)法通過(guò)instanceof等判斷。
當(dāng)一個(gè)接口為空對(duì)象{}時(shí),其相關(guān)的類(lèi)型校驗(yàn)總是通過(guò)
當(dāng)重復(fù)聲明同名接口時(shí),會(huì)合并聲明為一個(gè)接口(前提是兩次聲明的內(nèi)容無(wú)沖突)
- 可選屬性
接口中定義的屬性必須被實(shí)現(xiàn),若可不實(shí)現(xiàn),則應(yīng)使用可選屬性:key?: value; - 只讀屬性
僅能在對(duì)象創(chuàng)建時(shí)賦值,之后不能修改:readonly key:value; - 任意屬性(可索引類(lèi)型)
接口中未定義的屬性不可被實(shí)現(xiàn),若要實(shí)現(xiàn),則應(yīng)使用可索引類(lèi)型
一個(gè)接口中只能有一個(gè)任意屬性,且其他屬性的類(lèi)型必須是任意屬性的子集(若存在可選屬性,則任意屬性的屬性應(yīng)包含undefined或any)
interface Person {
name: string;
age?: number;
[propName: string]: string | number | undefined | number[];
}
let tom: Person = {
name: 'Tom',
age: 25,
gender: 'male',
params: [1,2,3]
};
對(duì)象接口
interface ILabel {
label: string;
name?: string;//可選參數(shù)
readonly age: number;//只讀參數(shù),僅能在對(duì)象剛創(chuàng)建時(shí)賦值,之后不能修改
todo?():void;//方法屬性
sayHello?:() => string;//方法屬性
}
function printLabel(labelledObj: ILabel ) {
...
}
printLabel( {size: 10, label: "Size 10 Object",age: 18} );//會(huì)報(bào)錯(cuò)
函數(shù)接口
函數(shù)參數(shù)名不需要與接口里定義的名字相匹配
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(src, sub) {
let result = src.search(sub);
if (result == -1) {
return false;
}else {
return true;
}
}
console.log(mySearch('hello','h'));
類(lèi)接口
類(lèi)使用implements實(shí)現(xiàn)接口
interface Wings {
fly(): void;
}
class Bird implements Wings {
fly() {
console.log('鳥(niǎo)在飛');
}
jump() {
console.log('鳥(niǎo)在跳');
}
}
混合接口
因JS靈活的特點(diǎn),一個(gè)變量可能同時(shí)可以作為函數(shù)被調(diào)用,又具有對(duì)象的屬性,此時(shí)其接口為一個(gè)混合接口
interface Counter {
(source: string, subString: string): boolean;
label: string;
}
接口繼承(擴(kuò)展)
interface Shape {
color: string;
}
interface PenStroke {
penWidth: number;
}
interface Square extends Shape, PenStroke {//一個(gè)接口可以繼承多個(gè)
sideLength: number;
}
let square = {} as Square;
square.color = "blue";
square.sideLength = 10;
square.penWidth = 5.0;//必須同時(shí)滿足兩個(gè)接口
TS中聲明一個(gè)類(lèi)時(shí),其實(shí)同時(shí)為該類(lèi)聲明了一個(gè)同名接口。因此和其他面向?qū)ο笳Z(yǔ)言不同,TS的接口可以繼承類(lèi),其本質(zhì)上即繼承該類(lèi)的接口
class Point {
x: number;
y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}
interface Point3d extends Point {
z: number;
}
let point3d: Point3d = {x: 1, y: 2, z: 3};
案例:用接口表示類(lèi)數(shù)組
function sum() {
let args: {
[index: number]: number;
length: number;
callee: Function;
} = arguments;
}
類(lèi)
TypeScript 除了實(shí)現(xiàn)了所有 ES6 中的類(lèi)的功能以外,還添加了一些新的用法。
強(qiáng)化了靜態(tài)屬性
采用了ES7提案,廢除了原型成員。
static不僅可修飾方法,也能修飾屬性。類(lèi)內(nèi)直接定義的無(wú)static屬性,均為實(shí)例屬性而非原型屬性。
實(shí)例屬性必須先在類(lèi)中聲明,然后再通過(guò)this賦值
可為構(gòu)造函數(shù)中的形參添加修飾符(訪問(wèn)修飾符 或 readonly)來(lái)簡(jiǎn)寫(xiě)該過(guò)程,自動(dòng)為類(lèi)聲明該實(shí)例屬性并賦值。
class Box {
name: string; # js中可以省略該行,但TS中會(huì)報(bào)錯(cuò)
constructor(name: string) {
this.name = name;
}
}
# 或簡(jiǎn)寫(xiě)為以下形式
class Box {
constructor(public name: string) {}
}
修飾符
只讀修飾符 readonly
被設(shè)置為只讀的屬性,只能在聲明時(shí)或構(gòu)造函數(shù)里被初始化,之后無(wú)法修改。-
訪問(wèn)修飾符
- public
默認(rèn)值,公有 - private
私有,不能在聲明它的類(lèi)的外部訪問(wèn)(包括實(shí)例)
構(gòu)造函數(shù)為私有時(shí),該類(lèi)不能被繼承和實(shí)例化
兩個(gè)類(lèi)即使有同名private成員也無(wú)法兼容,除非該成員有同一來(lái)源 - protected
受保護(hù),類(lèi)似private,但在子類(lèi)中也能訪問(wèn)
構(gòu)造函數(shù)為受保護(hù)時(shí),該類(lèi)只能被繼承,不能被實(shí)例化
- public
繼承(extends)
不同于python,JS、TS、C#都只能繼承單個(gè)類(lèi)
包含constructor函數(shù)的派生類(lèi)必須調(diào)用super(),它會(huì)執(zhí)行基類(lèi)的構(gòu)造方法。
class Animal{
name:string;
age:number;
constructor(theName:string='my name'){
this.name=theName;
}
move(distance:number=100){
console.log(this.name + 'move' + distance)
}
show(){
console.log('this is show')
}
}
let cat=new Animal('puppy');
cat.move(666)
class Dog extends Animal{
name:string;//子類(lèi)只能讓基類(lèi)的屬性更具體,而不能違反;不聲明時(shí)即和基類(lèi)相同
weight:number;
constructor(ddd){
super(ddd);//constructor內(nèi)super必須在this之前
this.weight=20;
}
move(){//子類(lèi)方法可以覆蓋基類(lèi)
console.log(this.name+this.weight);
super.show()
}
}
let dog=new Dog('ddd');
dog.move()
實(shí)現(xiàn)接口(implements)
和C#一樣,TS中的類(lèi)可以同時(shí)實(shí)現(xiàn)多個(gè)接口。
- 接口僅描述類(lèi)的部分成員
類(lèi)可自行聲明更多成員,不違反接口。 - 接口僅描述類(lèi)的公有成員
接口內(nèi)描述的成員都是public。 - 接口僅描述類(lèi)的實(shí)例成員
如靜態(tài)成員、constructor等,不在描述范圍內(nèi)。
interface IBox {
name: string;
}
interface IAnimal {
age: number;
}
class BoxAnimal implements IBox, IAnimal {
static currentTime(): Date { return new Date() };
name: string = "TK";
age: number;
sex: number = 0;
constructor(age: number) {
this.age = age;
}
}
let tk: BoxAnimal = new BoxAnimal(18);
console.log(tk);
抽象類(lèi)與抽象方法 abstract
- 帶有
abstract關(guān)鍵字的類(lèi)稱(chēng)為抽象類(lèi),是供其它類(lèi)繼承的基類(lèi),介于類(lèi)和接口之間,可以包含或不包含成員的實(shí)現(xiàn)細(xì)節(jié),但不能被實(shí)例化。 - 帶有
abstract關(guān)鍵字的方法稱(chēng)為抽象方法,只能在抽象類(lèi)中定義。抽象方法不包含具體實(shí)現(xiàn)并且必須在派生類(lèi)中實(shí)現(xiàn)。
abstract class Department {
constructor(public name: string) {
}
printName(): void {
console.log('Department name: ' + this.name);
}
abstract printMeeting(): void; // 必須在派生類(lèi)中實(shí)現(xiàn)
}
class AccountingDepartment extends Department {
constructor() {
super('Accounting and Auditing'); // constructors in derived classes must call super()
}
printMeeting(): void {
console.log('The Accounting Department meets each Monday at 10am.');
}
generateReports(): void {
console.log('Generating accounting reports...');
}
}
let department: Department; // ok to create a reference to an abstract type
department = new Department(); // error: cannot create an instance of an abstract class
department = new AccountingDepartment(); // ok to create and assign a non-abstract subclass
department.printName();
department.printMeeting();
department.generateReports(); // error: method doesn't exist on declared abstract type
把類(lèi)當(dāng)做接口使用
在TS中,接口(interface)和類(lèi)(class)的界限并不清晰,因此可以用一個(gè)類(lèi)實(shí)現(xiàn)另一個(gè)類(lèi),或者一個(gè)接口繼承一個(gè)類(lèi)。
同理,當(dāng)重復(fù)聲明同名類(lèi)時(shí),會(huì)合并聲明為一個(gè)類(lèi)(前提是兩次聲明的內(nèi)容無(wú)沖突)
此外,TS也符合鴨子類(lèi)型。注意在鴨子類(lèi)型中,a:A并不代表a是A或其子類(lèi)的實(shí)例,只是形狀相符而已。
interface IBox {
name: string;
}
interface IAnimal {
age: number;
}
class BoxAnimal implements IBox, IAnimal {
static currentTime(): Date { return new Date() };
name: string = "TK";
age: number;
sex: number = 0;
constructor(age: number) {
this.age = age;
}
}
let tk: BoxAnimal = new BoxAnimal(18);
type TBoxAnimal = BoxAnimal;
interface IBoxAnimal extends BoxAnimal { };
let tk_2: TBoxAnimal = { name: "11", age: 18, sex: 0 };
let tk_3: IBoxAnimal = { name: "11", age: 18, sex: 0 };
對(duì)象
Typescript 中的對(duì)象不能隨意增刪屬性字段:
let my_custom_date = 20;
(window as any).my_custom_date = 30;
var obj = {
name: 'ming',
};
// 事實(shí)上觸發(fā)了如下類(lèi)型推論:
// var obj: { name: string; } = {
// name: 'ming',
// };
// obj.age = 19; //報(bào)錯(cuò)
obj["age"] = 19; //通過(guò)字典形式可以繞開(kāi)類(lèi)型檢查
(obj as { name: string, age?: number; }).age = 19;//通過(guò)類(lèi)型斷言為obj添加可用屬性
函數(shù)
函數(shù)聲明方式定義函數(shù):
function sum(x: number, y: number): number {
return x + y;
}
函數(shù)表達(dá)式方式定義函數(shù):
let myAdd: (baseValue:number, increment:number) => number =
function(x: number, y: number): number { return x + y; };
注意在 TypeScript 的類(lèi)型定義中,=> 用來(lái)表示函數(shù)的定義,左邊是輸入類(lèi)型,需要用括號(hào)括起來(lái),右邊是輸出類(lèi)型。
參數(shù)
傳遞給一個(gè)函數(shù)的參數(shù)個(gè)數(shù)必須與函數(shù)期望的參數(shù)個(gè)數(shù)一致
- 可選參數(shù)
必須寫(xiě)在必選參數(shù)之后 :
function fn(a:number,b?:any){ }
fn(100)
- 參數(shù)默認(rèn)值
帶默認(rèn)值的參數(shù)也可以不傳。
不傳或傳入undefined時(shí),會(huì)采用默認(rèn)值
function fn(a:number,b='hello'){ }
fn(100)
- 剩余參數(shù)
function(a,b,...c: any[]){ }
- 函數(shù)重載
ts的函數(shù)重載比較特殊,重載和具體實(shí)現(xiàn)是分開(kāi)書(shū)寫(xiě)的。
根據(jù)傳入?yún)?shù)的不同,依次查找并嘗試重載列表。 因此定義重載時(shí),要把最精確的定義放在最前面。
function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string | void {
if (typeof x === 'number') {
return Number(x.toString().split('').reverse().join(''));
} else if (typeof x === 'string') {
return x.split('').reverse().join('');
}
}
注意,這里只有兩個(gè)重載:一個(gè)是接收對(duì)象另一個(gè)接收數(shù)字。
function reverse(x: number | string): number | string | void并不是重載列表的一部分,需包含重載列表里所有的出入?yún)⑶闆r,也可以寫(xiě)成function reverse(x: any): any。
泛型(Generics)
指在定義函數(shù)、接口或類(lèi)的時(shí)候,不預(yù)先指定具體的類(lèi)型,而在使用的時(shí)候再指定類(lèi)型的一種特性。
泛型函數(shù)
保證返回值的類(lèi)型與傳入?yún)?shù)的類(lèi)型相同。
通過(guò)重載也可以實(shí)現(xiàn)該功能,但使用泛型更方便。
function swap<T, U>(tuple: [T, U]): [U, T] {
return [tuple[1], tuple[0]];
}
泛型接口
interface GenericIdentityFn {
<T>(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn = identity;
也可以把泛型參數(shù)提前到接口名上,則使用泛型接口時(shí),需要定義泛型的類(lèi)型。
interface GenericIdentityFn<T> {
(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identity;
泛型類(lèi)
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };
泛型約束
泛型因未知其實(shí)際類(lèi)型,無(wú)法在函數(shù)內(nèi)調(diào)用屬性或方法。通過(guò)繼承接口可告知編譯器泛型的形狀,稱(chēng)之為泛型約束
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // Now we know it has a .length property, so no more error
return arg;
}
泛型之間也可以互相約束
function copyFields<T extends U, U>(target: T, source: U): T {
for (let id in source) {
target[id] = (<T>source)[id];
}
return target;
}
let x = { a: 1, b: 2, c: 3, d: 4 };
copyFields(x, { b: 10, d: 20 });
泛型參數(shù)默認(rèn)類(lèi)型
當(dāng)使用泛型時(shí)沒(méi)有在代碼中直接指定類(lèi)型參數(shù),從實(shí)際值參數(shù)中也無(wú)法推測(cè)出時(shí),這個(gè)默認(rèn)類(lèi)型就會(huì)起作用
function createArray<T = string>(length: number, value: T): Array<T> {
let result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}
內(nèi)置對(duì)象
詳見(jiàn)TypeScript核心庫(kù)定義文件
注意,NodeJS不是內(nèi)置對(duì)象,如需使用,則應(yīng)引入@types文件:
npm install @types/node --save-dev
- ECMA 內(nèi)置對(duì)象
Boolean、Error、Date、RegExp 等。 - DOM 和 BOM 的內(nèi)置對(duì)象
Document、HTMLElement、Event、NodeList 等。
可以將變量定義為這些類(lèi)型:
let b: Boolean = new Boolean(1);