那么我們開(kāi)始吧荷荤,
我們從基礎(chǔ)語(yǔ)言類(lèi)型開(kāi)始
JavaScript 的類(lèi)型分為兩種:原始數(shù)據(jù)類(lèi)型(Primitive data types)
和對(duì)象類(lèi)型(Object types)
。
原始數(shù)據(jù)類(lèi)型包括:布爾值、數(shù)值采缚、字符串鹰椒、null宝鼓、undefined
以及 ES6 中的新類(lèi)型 Symbol轩性。
本節(jié)主要介紹前五種原始數(shù)據(jù)類(lèi)型在 TypeScript
中的應(yīng)用。
原始數(shù)據(jù)類(lèi)型
布爾值
TypeScript
是用:
來(lái)進(jìn)行類(lèi)型申請(qǐng)的格遭。
let isDone: boolean = false;
// 編譯通過(guò)
// 后面約定哈街,未強(qiáng)調(diào)編譯錯(cuò)誤的代碼片段,默認(rèn)為編譯通過(guò)
注意如庭,使用構(gòu)造函數(shù) Boolean
創(chuàng)造的對(duì)象不是布爾值:
let createdByNewBoolean: boolean = new Boolean(1);
// index.ts(1,5): error TS2322: Type 'Boolean' is not assignable to type 'boolean'.
// 后面約定叹卷,注釋中標(biāo)出了編譯報(bào)錯(cuò)的代碼片段,表示編譯未通過(guò)
事實(shí)上 new Boolean()
返回的是一個(gè)Boolean
對(duì)象:
let createdByNewBoolean: Boolean = new Boolean(1);
直接調(diào)用 Boolean
也可以返回一個(gè) boolean
類(lèi)型:
let createdByBoolean: boolean = Boolean(1);
在 TypeScript 中坪它,boolean 是 JavaScript 中的基本類(lèi)型骤竹,而 Boolean 是 JavaScript 中的構(gòu)造函數(shù)。其他基本類(lèi)型(除了 null 和 undefined)一樣往毡,不再贅述蒙揣。
下面的類(lèi)型類(lèi)似:
數(shù)值
let age: number = 23;
字符串
let myName:string = 'Tom';
編譯結(jié)果為;
var isDone = false;
var age = 23;
var myName = 'Tom';
空值
在 JavaScript
沒(méi)有空值(Void
)的概念开瞭,在 TypeScript
中懒震,可以用 void
表示沒(méi)有任何返回值的函數(shù):
function alertName(): void {
alert("my name is Tom")
};
聲明一個(gè) void
類(lèi)型的變量沒(méi)有什么用罩息,因?yàn)槟阒荒軐⑺x值為 undefined
和 null
:
let unusable: void = undefined;
Null和Undefined
這兩個(gè)原始數(shù)據(jù)類(lèi)型比較有意思,他們的類(lèi)型變量只能賦值為他們本身个扰,undefined
為undefined
,null
只能為null
.
let u: undefined = undefined;
let n: null = null;
不過(guò)瓷炮,它和void
的區(qū)別是,他們兩個(gè)是所有類(lèi)型的子類(lèi)型递宅。也就是說(shuō)undefined
和null
類(lèi)型的變量娘香,可以賦值給number
類(lèi)型變量:
// 這樣不會(huì)報(bào)錯(cuò)
let num: number = undefined;
// 這樣也不會(huì)報(bào)錯(cuò)
let u: undefined;
let num: number = u;
而 void
類(lèi)型的變量不能賦值給 number
類(lèi)型的變量:
任意值
任意值(Any)用來(lái)表示允許賦值為任意類(lèi)型
那么什么是任意值類(lèi)型呢?
如果是一個(gè)普通類(lèi)型办龄,在賦值過(guò)程中改變類(lèi)型是不被允許的:
let myFavoriteNumber: string = 'seven';
myFavoriteNumber = 7;
編譯報(bào)錯(cuò):
hello.ts:25:1 - error TS2322: Type '7' is not assignable to type 'string'.
25 myFavoriteNumber = 7;
~~~~~~~~~~~~~~~~
但是any
類(lèi)型可以烘绽,允許被賦值為任意類(lèi)型。
let myFavoriteNumber: any = 'seven';
myFavoriteNumber = 7;
任意值的屬性和方法
在任意值上訪問(wèn)任何屬性都是允許的:
let anyThing: any = 'hello';
console.log(anyThing.myName);
console.log(anyThing.myName.firstName);
也允許調(diào)用任何方法:
let anyThing: any = 'Tom';
anyThing.setName('Jerry');
anyThing.setName('Jerry').sayHello();
anyThing.myName.setFirstName('Cat');
可以這樣認(rèn)為俐填,聲明一個(gè)變量為任意值后安接,對(duì)它的任何操作,返回的內(nèi)容的類(lèi)型都是任意值英融。
未聲明類(lèi)型的變量
如果變量在聲明的時(shí)候沒(méi)有指定類(lèi)型盏檐,那么它的默認(rèn)類(lèi)型為任意值類(lèi)型:
let something;
something = 'seven';
something = 7;
something.setName('Tom');
相當(dāng)于
let something: any;
something = 'seven';
something = 7;
something.setName('Tom');
類(lèi)型推論
如果沒(méi)有明確的指定類(lèi)型,那么TypeScript
會(huì)依照類(lèi)型推論Type Inference
的規(guī)則推斷出一個(gè)類(lèi)型矢赁。
什么是類(lèi)型推論呢糯笙?
例如:
let myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
// index.ts(2,1): error TS2322: Type 'number' is not assignable to type 'string'.
它就相當(dāng)于:
let myFavoriteNumber: string = 'seven';
myFavoriteNumber = 7;
// index.ts(2,1): error TS2322: Type 'number' is not assignable to type 'string'.
報(bào)的錯(cuò)誤都一樣贬丛,就是說(shuō)撩银,在你聲明變量的時(shí)候,如果你沒(méi)有設(shè)置類(lèi)型豺憔,但是你給它指定了具體的值额获,那么它就會(huì)推斷它的類(lèi)型為你制定值的類(lèi)型。
同理恭应,如果你在聲明變量的時(shí)候沒(méi)有指定值抄邀,那么它就推斷它的類(lèi)型為any
任意值類(lèi)型。
let myFavoriteNumber;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
聯(lián)合類(lèi)型
聯(lián)合類(lèi)型(Union Types
)表示取值可以為多種類(lèi)型中的一種昼榛。
let myFavoriteNumber: string | number = 'seven';
myFavoriteNumber = 7;
同樣是上面的代碼境肾,你設(shè)置了字符串和數(shù)字,那么它就可以設(shè)置這兩種胆屿。
let myFavoriteNumber: string | number ;
myFavoriteNumber = false;
// index.ts(2,1): error TS2322: Type 'boolean' is not assignable to type 'string | number'.
// Type 'boolean' is not assignable to type 'number'.
聯(lián)合類(lèi)型是用豎線 |
來(lái)分割每個(gè)類(lèi)型奥喻。
這里的含義是,你可以是字符串或者數(shù)字非迹,但是不可以是其他的類(lèi)型环鲤。
訪問(wèn)聯(lián)合類(lèi)型的屬性或方法
當(dāng)TypeScript
不確定一個(gè)聯(lián)合類(lèi)型的變量到底是哪個(gè)類(lèi)型的時(shí)候,我們只能訪問(wèn)此聯(lián)合類(lèi)型的所有類(lèi)型里共有的屬性或方法:
function getLength(something: string | number): number {
return something.length;
}
hello.ts:39:22 - error TS2339: Property 'length' does not exist on type 'string
上例中憎兽,length
不是string
和number
的共有屬性冷离,所以會(huì)報(bào)錯(cuò)吵冒。
訪問(wèn)string
和number
的共有屬性是沒(méi)有問(wèn)題的:
function getString(something: string | number): string {
return something.toString();
}
聯(lián)合類(lèi)型的變量在賦值的時(shí)候,會(huì)根據(jù)類(lèi)型推論的規(guī)則推斷出一個(gè)類(lèi)型:
let myFavoriteNumber: string|number;
myFavoriteNumber = 'seven';
console.log(myFavoriteNumber.length);
myFavoriteNumber = 7;
console.log(myFavoriteNumber.lenght);
// index.ts(5,30): error TS2339: Property 'length' does not exist on type 'number'.
上面的第二行西剥,類(lèi)型推斷字符串痹栖,所以length
不報(bào)錯(cuò),
而第四行瞭空,類(lèi)型推斷為數(shù)字结耀,所以length
為不報(bào)錯(cuò)。
對(duì)象的類(lèi)型——接口
這個(gè)在java
語(yǔ)言中非常重要的概念匙铡,有一個(gè)說(shuō)法是面向接口編程
图甜。在TypeScript
中,我們使用接口interface
來(lái)定義對(duì)象的類(lèi)型鳖眼。
什么是接口
在面向?qū)ο笳Z(yǔ)言中黑毅,它是對(duì)行為的抽象,而具體如何行動(dòng)需要由類(lèi)classes
去實(shí)現(xiàn)implements
.
而TypeScript
中的接口是一個(gè)非常靈活的概念钦讳,除了可用于一部分行為進(jìn)行抽象外矿瘦,也常用于對(duì)象的形狀Shape
進(jìn)行概括。
例如:
interface Person {
name:string;
age:number;
}
let tom:Person = {
name:"Tom",
age:23
};
這個(gè)有點(diǎn)想抽象類(lèi)愿卒,我們看到上面代碼中缚去,我們創(chuàng)建了一個(gè)對(duì)象tom
,然后把它的類(lèi)型設(shè)置為接口Person
琼开。這樣的話易结,我們就約束了tom
的形狀必須和接口Person
一直。接口一般首字母大寫(xiě)柜候。有的編程語(yǔ)言中會(huì)建議接口的名稱(chēng)加上I
為前綴搞动。
因?yàn)槟阍O(shè)定了對(duì)象的類(lèi)型是接口Person
,所以必須完全一致渣刷,少一些屬性和多一些屬性鹦肿,通通不允許:
interface Person {
name:string;
age:number;
}
let tom:Person = {
name:"Tom",
};
//hello.ts:59:5 - error TS2322: Type '{ name: string; }' is //not assignable to type 'Person'.
// Property 'age' is missing in type '{ name: string; }'.
interface Person {
name:string;
age:number;
}
let tom:Person = {
name:"Tom",
age:23,
gender:'male'
};
//hello.ts:62:5 - error TS2322: Type '{ name: string; age: //number; gender: string; }' is not assignable to type //'Person'.
// Object literal may only specify known properties, and //'gender' does not exist in type 'Person'.
所以,賦值的時(shí)候辅柴,變量的形狀必須和接口的形狀保持一致箩溃。
可是我不想保持一致怎么辦呢?可選屬性出場(chǎng)
可選屬性
可選屬性是通過(guò)變量后面加一個(gè)?
問(wèn)號(hào)來(lái)實(shí)現(xiàn)的碌嘀,它的意思是你可以選擇這個(gè)屬性不存在涣旨。但是不可以添加未定義的屬性。
interface Person {
name:string;
age?:number;
}
let tom:Person = {
name:"Tom",
};
可選屬性筏餐,你可以存在或者不存在
interface Person {
name:string;
age?:number;
}
let tom:Person = {
name:"Tom",
age:23,
gender:'male'
};
//hello.ts:62:5 - error TS2322: Type '{ name: string; age: //number; gender: string; }' is not assignable to type //'Person'.
// Object literal may only specify known properties, and //'gender' does not exist in type 'Person'.
不可以添加不存在的屬性开泽。
對(duì)象的類(lèi)型 接口的意義就是為了約束對(duì)象的創(chuàng)建。
任意類(lèi)型
有時(shí)候我們希望一個(gè)借口允許有任意的屬性魁瞪,可以使用下面的方式:
interface Person {
name:string;
age?:number;
[propName: string]:any;
}
let tom:Person = {
name:"Tom",
age:23,
gender:'male'
};
我們通過(guò)[propName: string]
定義了任意屬性取string
的值穆律,而我們需要注意的是惠呼,一旦定義了任意屬性,那么確定屬性和可選屬性都必須是它的子屬性峦耘。
interface Person {
name:string;
age?:number;
[propName: string]:string;
}
let tom:Person = {
name:"Tom",
age:23,
gender:'male'
};
我們把上面的any
改為string
,那么不確定屬性age
為number
剔蹋,不屬于string
,就報(bào)錯(cuò)了辅髓。
編譯的結(jié)果:
hello.ts:56:5 - error TS2411: Property 'age' of type 'number' is not assignable to string index type 'string'.
56 age?:number;
~~~
hello.ts:60:5 - error TS2322: Type '{ name: string; age: number; gender: string; }' is not assignable to type 'Person'.
Property 'age' is incompatible with index signature.
Type 'number' is not assignable to type 'string'.
60 let tom:Person = {
只讀屬性
我們還可以設(shè)置只讀類(lèi)型泣崩,只有在創(chuàng)建的時(shí)候賦值,其他的時(shí)候不可以賦值洛口,那么就可以使用readonly
定義只讀屬性了矫付。
interface Person {
readonly id:number;
name:string;
age?:number;
[propName: string]:any;
}
let tom:Person = {
id:12345,
name:"Tom",
age:23,
gender:'male'
};
tom.id = 2222;
//hello.ts:68:5 - error TS2540: Cannot assign to 'id' because //it is a constant or a read-only property.
//68 tom.id = 2222;
類(lèi)似于上面的代碼,我們把readonly
放在屬性名稱(chēng)的前面,在上面的tom
對(duì)象中第焰,我們創(chuàng)建的時(shí)候就已經(jīng)直接賦值了买优,所以在后面再次賦值的時(shí)候,就報(bào)錯(cuò)挺举。
注意:只讀的約束存在于第一次給對(duì)象賦值的時(shí)候杀赢,而不是第一次給只讀屬性賦值的時(shí)候。
interface Person {
readonly id:number;
name:string;
age?:number;
[propName: string]:any;
}
let tom:Person = {
name:"Tom",
age:23,
gender:'male'
};
tom.id = 2222;
hello.ts:61:5 - error TS2322: Type '{ name: string; age: number; gender: string; }' is not assignable to type 'Person'.
Property 'id' is missing in type '{ name: string; age: number; gender: string; }'.
61 let tom:Person = {
~~~
hello.ts:68:5 - error TS2540: Cannot assign to 'id' because it is a constant or a read-only property.
68 tom.id = 2222;
上面報(bào)錯(cuò)有兩次湘纵,一是在創(chuàng)建對(duì)象的時(shí)候脂崔,沒(méi)有給只讀屬性id
賦值,二是它是只讀屬性梧喷,不可以在此賦值砌左。
關(guān)于接口行為的約束,我們?cè)诤竺鏁?huì)有詳細(xì)的章節(jié)伤柄。
數(shù)組的類(lèi)型
在TypeScript
中绊困,數(shù)組類(lèi)型有多重定義方式文搂,比較靈活适刀。
「類(lèi)型 + 方括號(hào)」表示法
和java
的類(lèi)似
let array:number[] = [1,2,3,4,5,6];
let sty_arr:string[] = ['1','2'];
數(shù)組中不可以出現(xiàn)其他的數(shù)據(jù)類(lèi)型:
let array:number[] = [1,2,3,4,5,6,"1"];
hello.ts:70:35 - error TS2322: Type 'string' is not assignable to type 'number'.
70 let array:number[] = [1,2,3,4,5,6,"1"];
我們?cè)囈幌率欠窨梢月暶髀?lián)合類(lèi)型的數(shù)組,既包含字符串又包含數(shù)字
let com_arr: string | number [] = ["1",1];
hello.ts:73:5 - error TS2322: Type '(string | number)[]' is not assignable to type 'string | number[]'.
Type '(string | number)[]' is not assignable to type 'number[]'.
Type 'string | number' is not assignable to type 'number'.
Type 'string' is not assignable to type 'number'.
73 let com_arr: string | number [] = ["1",1];
看上面錯(cuò)誤煤蹭,這樣聲明的數(shù)組是不行的笔喉。需要改成下面這樣。
let com_arr: (string | number) [] = ["1",1];
果然可以硝皂。666常挚,不過(guò)我們還是不要這樣用了,你用TypeScript
就是為了約束稽物,你這樣玩還不如直接寫(xiě):
let com_arr = ["1", 1];
數(shù)組的泛型
我們也可以用數(shù)組的泛型來(lái)展示數(shù)組奄毡。Array<elemType>
let array: Array<number> = [1,2,3,4,5];
let array1: Array<string> = ["1","2"];
let array3: Array<string|number> = ["1","2",1];
let array4:Array<any> = [1,"2",{"a":1}];
同樣我們可以用any
來(lái)定義數(shù)組。
關(guān)于泛型贝或,可以參考泛型一章.
用接口表示數(shù)組
interface NumberArray {
[index:number]:number;
}
// let array:NumberArray = [1,2,3,4];
let array :NumberArray = ["a"];
hello.ts:86:27 - error TS2322: Type 'string' is not assignable to type 'number'.
86 let array :NumberArray = ["a"];
hello.ts:82:5
82 [index:number]:number;
~~~~~~~~~~~~~~~~~~~~~~
The expected type comes from this index signature.
NumberArray
表示:只要index
的類(lèi)型是number
,那么值必須是number
如果我們?cè)O(shè)置的數(shù)組是字符串的話吼过,那么它會(huì)報(bào)錯(cuò)锐秦。
類(lèi)數(shù)組
類(lèi)數(shù)組不是數(shù)組類(lèi)型,比如內(nèi)置對(duì)象arguments:
function sum() {
let args:number [] = arguments;
}
hello.ts:89:9 - error TS2322: Type 'IArguments' is not assignable to type 'number[]'.
Property 'pop' is missing in type 'IArguments'.
89 let args:number [] = arguments;
我們可以看到上面的錯(cuò)誤說(shuō)的是IArguments
類(lèi)型無(wú)法匹配為nujber []
類(lèi)型盗忱。所以我們可以這樣寫(xiě):
function sum() {
let args:IArguments = arguments;
}
沒(méi)有報(bào)錯(cuò)酱床,妥妥的。
函數(shù)的類(lèi)型
大家要記得趟佃,函數(shù)是JavaScript的一等公民
函數(shù)聲明
在JavaScript
中扇谣,有兩種常見(jiàn)的定義函數(shù)的方式--函數(shù)聲明和函數(shù)表達(dá)式:
//函數(shù)聲明 (Function Declaration)
function sum(x,y){
return x+y;
}
//函數(shù)表達(dá)式 (Function Expression)
let mySum = function(x,y){
return x + y;
}
一個(gè)函數(shù)有輸入和輸出,要在 TypeScript
中對(duì)其進(jìn)行約束闲昭,需要把輸入和輸出都考慮到罐寨,其中函數(shù)聲明的類(lèi)型定義較簡(jiǎn)單:
function sum(x:number,y:number):number {
return x + y;
}
注意:輸入多余的或者少輸入都會(huì)報(bào)錯(cuò)。我就不在這里試了序矩。
函數(shù)表達(dá)式
感覺(jué)這里是個(gè)坑衩茸。
聲明一個(gè)函數(shù)表達(dá)式,會(huì)寫(xiě)成這樣:
let mySum = function (x: number, y: number):number {
return x + y;
}
沒(méi)有報(bào)錯(cuò)贮泞,可以編譯楞慈,實(shí)際上上面的代碼只對(duì)燈油右側(cè)的匿名函數(shù)進(jìn)行了類(lèi)型定義,而等號(hào)左邊的mySum
啃擦,是對(duì)賦值操作進(jìn)行類(lèi)型推論出來(lái)的囊蓝。如果我們需要手動(dòng)為它添加類(lèi)型,則應(yīng)該寫(xiě)成這樣令蛉。
let mySum:(x:number,y:number)=>number = function (x: number, y: number):number {
return x + y;
}
這里不要把TypeScript
的=>
和ES6
的=>
混淆了聚霜。
怎么可能不混淆嗎会油?
在TypeScript
的類(lèi)型定義中摄凡,=>
用來(lái)表示函數(shù)的定義,左邊是輸入的參數(shù)的類(lèi)型蟋软,右邊是返回的類(lèi)型祷安。
在ES6
中姥芥,=>
表示箭頭函數(shù)。不在介紹汇鞭。
用接口定義函數(shù)的形狀
那么我們現(xiàn)在用接口來(lái)定義個(gè)函數(shù)所需要的形狀:
interface SearchFunc {
(source:string,subString:string):boolean;
}
let mySearch:SearchFunc = function (source:string,subString:string) {
return source.search(subString) !== -1;
}
我們用接口定義了函數(shù)的形狀凉唐,左邊是輸入的類(lèi)型,右邊是輸出的類(lèi)型霍骄。
可選參數(shù)
前面我們說(shuō)道輸入多余或者少輸入都會(huì)報(bào)錯(cuò)台囱,那么如何定義和選擇的參數(shù)呢?與接口中的可選屬性類(lèi)型读整,我們用?
表示可選的參數(shù):
function buildName(firstName: string, lastName?: string) {
if (lastName) {
return firstName + ' ' + lastName;
} else {
return firstName;
}
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');
需要注意的是簿训,可選參數(shù)必須接在必需參數(shù)后面。換句話說(shuō),可選參數(shù)后面不允許再出現(xiàn)必須參數(shù)了:
function buildName(firstName?: string, lastName: string) {
if (firstName) {
return firstName + ' ' + lastName;
} else {
return lastName;
}
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName(undefined, 'Tom');
// index.ts(1,40): error TS1016: A required parameter cannot follow an optional parameter.
參數(shù)默認(rèn)值
TypeScript
中參數(shù)的默認(rèn)值和ES6
一樣的寫(xiě)法强品,TypeScript
會(huì)將添加了默認(rèn)值的參數(shù)識(shí)別為可選參數(shù):
function buildName(firstName:string,lastName:string = "Cat") {
return firstName +" " +lastName;
}
let tomcat = buildName('Tom','Cat');
let tom = buildName('Tom');
此時(shí)就不受可選參數(shù)必須接在必須參數(shù)后面
的限制了:
function buildName(firstName:string,lastName:string = "Cat") {
return firstName +" " +lastName;
}
let tomcat = buildName('Tom','Cat');
let tom = buildName(undefined,'Tom');
剩余參數(shù)
ES6
中豺总,可以使用 ...rest
的方式獲取函數(shù)中的剩余參數(shù)(rest
參數(shù)):
function push(array,...items) {
items.forEach(function (item) {
array.push(item);
});
}
let a = [];
push(a,2,3,4);
我們可以看到,實(shí)際上items
是一個(gè)數(shù)組择懂,所以我們可以用數(shù)組的方式來(lái)定義它喻喳。
function push(array:any [],...items:any []) {
items.forEach(function (item) {
array.push(item);
});
}
let a = [];
push(a,2,3,4);
需要注意的是,rest
參數(shù)只能是最后一個(gè)參數(shù)困曙。
重載
重載允許一個(gè)函數(shù)接受不同數(shù)量或者不同類(lèi)型的參數(shù)時(shí)表伦,做出不同的處理。
比如我們實(shí)現(xiàn)下面的函數(shù)慷丽。利用聯(lián)合類(lèi)型蹦哼,我們可以這樣實(shí)現(xiàn)。
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('');
}
}
不過(guò)這樣有一個(gè)缺點(diǎn)要糊,就是不能夠精確的表達(dá)纲熏,輸入為數(shù)字的時(shí)候,輸出也應(yīng)該是數(shù)字锄俄,輸入字符串的時(shí)候局劲,輸出也應(yīng)該是字符串。
我們可以使用多個(gè)reverse
的函數(shù)類(lèi)型:
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('');
}
}
上例中奶赠,我們重復(fù)定義了多次函數(shù)reverse
鱼填,幾次都是函數(shù)定義,最后一次是函數(shù)實(shí)現(xiàn)毅戈,在編輯的代碼提示中苹丸,可以正確的看到前兩個(gè)提示。
需要注意的是苇经,TypeScript
會(huì)優(yōu)先從最前面的函數(shù)定義開(kāi)始匹配赘理,所以多個(gè)函數(shù)定義如果有包含關(guān)系,需要優(yōu)先把精確的電影以寫(xiě)在前面扇单。
類(lèi)型斷言
類(lèi)型斷言(Type Assertion) 可以用來(lái)手動(dòng)指定一個(gè)值的類(lèi)型商模。但是它并不是類(lèi)型轉(zhuǎn)換。
語(yǔ)法
<類(lèi)型>值
或
值 as 類(lèi)型
在tsx
語(yǔ)法中必須用后一種令花。
例如:將一個(gè)聯(lián)合類(lèi)型的變量指定為更加具體的的類(lèi)型阻桅。
之前提到過(guò),當(dāng) TypeScript 不確定一個(gè)聯(lián)合類(lèi)型的變量到底是哪個(gè)類(lèi)型的時(shí)候兼都,我們只能訪問(wèn)此聯(lián)合類(lèi)型的所有類(lèi)型里共有的屬性或方法:
function getLength(something:string|number):number {
return something.length;
}
hello.ts:154:22 - error TS2339: Property 'length' does not exist on type 'string | number'.
Property 'length' does not exist on type 'number'.
154 return something.length;
我們有時(shí)候需要在還不確定類(lèi)型的時(shí)候就訪問(wèn)其中的一個(gè)類(lèi)型的屬性或方法,比如:
function getLength(something:string|number):number {
if(something.length){
return something.length;
}else{
return something.toString.length;
}
}
hello.ts:154:17 - error TS2339: Property 'length' does not exist on type 'string | number'.
Property 'length' does not exist on type 'number'.
154 if(something.length){
~~~~~~
hello.ts:155:25 - error TS2339: Property 'length' does not exist on type 'string | number'.
Property 'length' does not exist on type 'number'.
155 return something.length;
可以看到上面的報(bào)錯(cuò)稽寒,這個(gè)時(shí)候我們就可以使用類(lèi)型斷言扮碧,將something
斷言成string
:
function getLength(something:string|number):number {
if((<string>something).length){
return (<string>something).length;
}else{
return something.toString.length;
}
}
類(lèi)型斷言的用法如上,在需要斷言的變量前加上<Type>
就可以。
類(lèi)型斷言不是類(lèi)型轉(zhuǎn)換慎王,斷言成一個(gè)聯(lián)合類(lèi)型中不存在的類(lèi)型是不允許的蚓土。
function boBoolean(something:string|number):boolean {
return <boolean>something;
}
hello.ts:162:12 - error TS2352: Conversion of type 'string | number' to type 'boolean' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
Type 'number' is not comparable to type 'boolean'.
162 return <boolean>something;
類(lèi)型斷言不是類(lèi)型轉(zhuǎn)換,因?yàn)槟悴荒馨阉鼜?qiáng)制轉(zhuǎn)換為不存在的類(lèi)型赖淤。
聲明文件
內(nèi)置對(duì)象
JavaScript
中有很多內(nèi)置對(duì)象蜀漆,它們可以直接在 TypeScript
中當(dāng)做定義好了的類(lèi)型。
內(nèi)置對(duì)象是指根據(jù)標(biāo)準(zhǔn)在全局作用域(Global)
上存在的對(duì)象咱旱。這里的標(biāo)準(zhǔn)是指 ECMAScript 和其他環(huán)境(比如 DOM)的標(biāo)準(zhǔn)确丢。
ECMAScript 的內(nèi)置對(duì)象
ECMAScript
標(biāo)準(zhǔn)提供的內(nèi)置對(duì)象有:
Boolean
,String
,Error
,Date
,RegExp
等
我們都可以在TypeScript
中將變量定義為這些類(lèi)型。
let b:Boolean = new Boolean(1);
let e:Error = new Error("error occurred");
let d:Date = new Date();
let r:RegExp = /[a-z]/;
let s:String = new String("a");
let n:Number = new Number(1);
更多的內(nèi)置對(duì)象吐限,可以查看MDN的文檔
而他們的定義文件鲜侥,則在 TypeScript 核心庫(kù)的定義文件中。
DOM 和 BOM 的內(nèi)置對(duì)象
DOM和BOM提供的內(nèi)置對(duì)象:
Document诸典、HTMLElement描函、Event、NodeList
等狐粱。
TypeScript
中經(jīng)常用到這些類(lèi)型:
let body:HTMLElement = document.body;
let allDiv:NodeList = document.querySelectorAll('div');
document.addEventListener('click',function (e:MouseEvent) {
//DO something
})
它們同樣定義在 TypeScript 核心庫(kù)的定義文件中舀寓。
大家加油。肌蜻。基公。