TypeScript入門教程完整版_第1頁
TypeScript入門教程完整版_第2頁
TypeScript入門教程完整版_第3頁
TypeScript入門教程完整版_第4頁
TypeScript入門教程完整版_第5頁
已閱讀5頁,還剩155頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

ypeScript入門教程目錄\h基礎\h原始數(shù)據(jù)類型\h任意值\h類型推論\h聯(lián)合類型\h對象的類型\h數(shù)組的類型\h函數(shù)的類型\h類型斷言\h聲明文件\h內置對象\h進階\h類型別名\h字符串字面量類型\h元組\h枚舉\h類\h類與接口\h泛型\h聲明合并什么是ypeScript首先,我對的理解如下:\h是JavaScript的一個超集,主要提供了類型系統(tǒng)和對ES6由Mi\h碼開源于Gub其次引\h用isatypedsupersetofJavaciptthatcomptoplainJAnybrowse.Ayhos.AnyOS.Opensource.翻譯成中文即是:是JavaScript的類型的超集,它可以編譯成純JavaScript。編譯出來的JavaScript可以運行在任何瀏覽器上。編譯工具可以運行在任何服務器和任何系統(tǒng)上。ypeScr是開源的。為什么選擇ypeScrit\h舉了一些優(yōu)勢,不過我更愿意自己總結一下:類型系統(tǒng)實際上是最好的文檔,大部分的函數(shù)看看類型的定義就可以知道如何使用了可以在編譯階段就發(fā)現(xiàn)大部分錯誤,這總比在運行時候出錯好增強了編輯器和IE的功能,包括代碼補全、接口提示、跳轉到定義、重構等是JavaScript的超集,.js文件可以直接重命名為.ts即可即使不顯式的定義類型,也能夠自動做\h出可以定義從簡單到復雜的一切類型即使ypeScript編譯報錯,也可以生成JavaScrpt兼容第三方庫,即使第三方庫不是用pt寫的,也可以編寫單獨的類型8什么是ypeScript文件供ypeScript大部分第三方庫都有提供給pt的類型定義文件Google開發(fā)的Angular2就是使用ES6的一部分特性是借鑒的eScript的(這條需要來源)擁抱了ES6規(guī)范,也支持部分ES7任何事物都是有兩面性的,我認為pt的弊端在于:有一定的學習成本,需要理解接口(Gener(Enums且它的中文資料也不多短期可能會增加一些開發(fā)成本,畢竟要多寫一些類型的定義,不過對于一個需要長期維護的項目,ypeScr能夠減少其維護成本(這條需要來源)集成到構建流程需要一些工作量可能和一些庫結合的不是很完美(這條需要舉例)大家可以根據(jù)自己團隊和項目的情況判斷是否需要使用y\h上一章:簡介\h下一章:安裝9安裝ypeScript安裝ypeScriptnpminstall-gtypescript安裝完成之后,就有了tsc命令。編譯一個文件很簡單:tschello.ts我們約定使用編寫的文件以.ts為后綴。編輯器最大的優(yōu)勢之一便是增強了編輯器和IDE提示、跳轉到定義、重構等。主流的編輯器都支持Script用\hStudioCode。它是一款開源,跨終端的輕量級編輯器,內置了ypeScript另外它本身也\h是用ypeScript下載安裝\h:ttps:.visualstu.co/獲取其他編輯器或I對t\hSublimeext\hAtom\h\h\hEmacs\hEcipse\hStudio2015\hStudio201310安裝ypeScript\h上一章:什么是\h下一章:elloHeloHelloypeScript我們從一個簡單的例子開始。將以下代碼復制到hello.ts中:functionsayHello(person:string){return'Hello,'+person;}letuser='XcatLiu';console.log(sayHello(user));然后執(zhí)行tschello.ts這時候會生成一個編譯好的文件hello.jsfunctionsayHello(person){return'Hello,'+person;}varuser='XcatLiu';console.log(sayHello(user));:指定變量的類型,:的前后有沒有空格都可以。上述例子中,我們用:指定person參數(shù)類型為string。但是編譯為js后,并沒有什么檢查的代碼被插入進來。只會進行靜態(tài)檢查,如果發(fā)現(xiàn)有錯誤,編譯的時候就會報錯。let是ES6中的關鍵字,和var類似,用于定義一個局部變量,可以參閱\hlet和const下面嘗試把這段代碼編譯一下:12HelofunctionsayHello(person:string){return'Hello,'+person;}letuser=[0,1,2];console.log(sayHello(user));編輯器中會提示錯誤,編譯的時候也會出錯:index.ts(6,36):errorTS2345:Argumentoftype'number[]'isnotassignabletoparameteroftype'string'.但是還是生成了jfunctionsayHello(person){return'Hello,'+person;}varuser=[0,1,2];console.log(sayHello(user));編譯的時候即使報錯了,還是會生成編譯結果,我們仍然可以使用這個編譯之后的文件。如果要在報錯的時候終止js文件的生成,可以在tsconfig.json中配置noEmitOnError即可。關于tsconfig.json\h官方手冊\h中文版\h上一章:安裝\h下一章:基礎13基礎基礎本部分介紹了中的常用類型和一些基本概念,旨在讓大家對yp有個初步的理解。具體內容包括:\h原始數(shù)據(jù)類型\h任意值\h類型推論\h聯(lián)合類型\h對象的類型\h數(shù)組的類型\h函數(shù)的類型\h類型斷言\h聲明文件\h內置對象\h上一章:ello\h下一章:原始數(shù)據(jù)類型14原始數(shù)據(jù)類型原始數(shù)據(jù)類型JavaScript\h(rmitivedtatyes)和對象類型(bjecttypes\h原始數(shù)據(jù)類型包括:布爾值、數(shù)值、字符串、null、ndefined以及ES6\h的新類型Symbol本節(jié)主要介紹前五種原始數(shù)據(jù)類型在pt中的應用。布爾值布爾值是最基礎的數(shù)據(jù)類型,在ptboolean定義布爾值類型:letisDone:boolean=false;//編譯通過//后面約定,未強調編譯錯誤的代碼片段,默認為編譯通過注意,使用構造函數(shù)Boolean創(chuàng)造的對象不是布爾值:letcreatedByNewBoolean:boolean=newBoolean(1);//index.ts(1,5):errorTS2322:Type'Boolean'isnotassignabletotype'boolean'.//后面約定,未強調編譯錯誤的代碼片段,默認為編譯通過事實上newBoolean()返回的是一個Boolean對象:letcreatedByNewBoolean:Boolean=newBoolean(1);直接調用Boolean也可以返回一個boolean類型:15原始數(shù)據(jù)類型letcreatedByBoolean:boolean=Boolean(1);在中,boolean是JavaScript中的基本類型,而Boolean是JavaScriptnull和undefined不再贅述。數(shù)值使用number定義數(shù)值類型:letdecLiteral:number=6;lethexLiteral:number=0xf00d;//ES6中的二進制表示法letbinaryLiteral:number=0b1010;//ES6中的八進制表示法letoctalLiteral:number=0o744;letnotANumber:number=NaN;letinfinityNumber:number=Infinity;編譯結果:vardecLiteral=6;varhexLiteral=0xf00d;//ES6中的二進制表示法varbinaryLiteral=10;//ES6中的八進制表示法varoctalLiteral=484;varnotANumber=NaN;varinfinityNumber=Infinity;其中0b1010和0o744是\hES6它們會被編譯為十進制數(shù)字。字符串16原始數(shù)據(jù)類型使用string定義字符串類型:letmyName:string='XcatLiu';letmyAge:number=25;//模板字符串letsentence:string=`Hello,mynameis${myName}.I'llbe${myAge+1}yearsoldnextmonth.`;編譯結果:varmyName='XcatLiu';varmyAge=25;//模板字符串varsentence="Hello,mynameis"+myName+".\nI'llbe"+(myAge+1)+"yearsoldnextmonth.";其中`用來定義\hES6中的模板字符串,${expr}用來在模板字符串中嵌入表達式??罩礘avaScript沒有空值(oid在rptvoid表示沒有任何返回值的函數(shù):functionalertName():void{alert('Mynameisxcatliu');}聲明一個void類型的變量沒有什么用,因為你只能將它賦值為undefined和nullletunusable:void=undefined;Nul和Undefined17原始數(shù)據(jù)類型在中,可以使用null和undefined來定義這兩個原始數(shù)據(jù)類型:letu:undefined=undefined;letn:null=null;undefined類型的變量只能被賦值為undefined,null類型的變量只能被賦值為null與void的區(qū)別是,undefined和null是所有類型的子類型。也就是說undefined類型的變量,可以賦值給number類型的變量://這樣不會報錯letnum:number=undefined;//這樣也不會報錯letu:undefined;letnum:number=u;而void類型的變量不能賦值給number類型的變量:letu:void;letnum:number=u;//index.ts(2,5):errorTS2322:Type'void'isnotassignabletotype'number'.參考\hBasicyes\h()\hPrdtatypes\hES6Symbol\hES6中的二進制和八進制表示法\hES6中的模板字符串18原始數(shù)據(jù)類型\h上一章:基礎\h下一章:任意值19任意值任意值任意值(什么是任意值類型如果是一個普通類型,在賦值過程中改變類型是不被允許的:letmyFavoriteNumber:string='seven';myFavoriteNumber=7;//index.ts(2,1):errorTS2322:Type'number'isnotassignabletotype'string'.但如果是any類型,則允許被賦值為任意類型。letmyFavoriteNumber:any='seven';myFavoriteNumber=7;任意值的屬性和方法在任意值上訪問任何屬性都是允許的:letanyThing:any='hello';console.log(anyThing.myName);console.log(anyThing.myName.firstName);也允許調用任何方法:letanyThing:any='XcatLiu';anyThing.setName('JerryLee');anyThing.setName('JerryLee').sayHello();anyThing.myName.setFirstName('Cat');20任意值可以認為,聲明一個變量為任意值之后,對它的任何操作,返回的內容的類型都是任意值。未聲明類型的變量變量如果在聲明的時候,未指定其類型,那么它會被識別為任意值類型:letsomething;something='seven';something=7;something.setName('JerryLee');等價于letsomething:any;something='seven';something=7;something.setName('JerryLee');參考\hBasicyesAny\h()\h上一章:原始數(shù)據(jù)類型\h下一章:類型推論21類型推論類型推論如果沒有明確的指定類型,那么pt會依照類型推論(Inference規(guī)則推斷出一個類型。什么是類型推論以下代碼雖然沒有指定類型,但是會在編譯的時候報錯:letmyFavoriteNumber='seven';myFavoriteNumber=7;//index.ts(2,1):errorTS2322:Type'number'isnotassignabletotype'string'.事實上,它等價于:letmyFavoriteNumber:string='seven';myFavoriteNumber=7;//index.ts(2,1):errorTS2322:Type'number'isnotassignabletotype'string'.會在沒有明確的指定類型的時候推測出一個類型,這就是類型推論。在2.1推斷成any類型而完全不被類型檢查:letmyFavoriteNumber;myFavoriteNumber='seven';myFavoriteNumber=7;2.1中,編譯器會考慮對myFavoriteNumber的最后一次賦值來檢查類型:\h例22類型推論參考\hInference\h()\h2.1ReleaseNote\h上一章:任意值\h下一章:聯(lián)合類型23聯(lián)合類型聯(lián)合類型聯(lián)合類型(簡單的例子letmyFavoriteNumber:string|number;myFavoriteNumber='seven';myFavoriteNumber=7;letmyFavoriteNumber:string|number;myFavoriteNumber=true;//index.ts(2,1):errorTS2322:Type'boolean'isnotassignabletotype'string|number'.//Type'boolean'isnotassignabletotype'number'.聯(lián)合類型使用|分隔每個類型。這里的string|number的含義是,允許myFavoriteNumber的類型是string或者number,但是不能是其他類型。訪問聯(lián)合類型的屬性或方法當不確定一個聯(lián)合類型的變量到底是哪個類型的時候,我們只能訪問此聯(lián)合類型的所有類型里共有的屬性或方法:24聯(lián)合類型functiongetLength(something:string|number):number{returnsomething.length;}//index.ts(2,20):errorTS2339:Property'length'doesnotexistontype'string|number'.//Property'length'doesnotexistontype'number'.上例中,length不是string和number的共有屬性,所以會報錯。訪問string和number的共有屬性是沒問題的:functiongetString(something:string|number):string{returnsomething.toString();}聯(lián)合類型的變量在被賦值的時候,會根據(jù)類型推論的規(guī)則推斷出一個類型:letmyFavoriteNumber:string|number;myFavoriteNumber='seven';console.log(myFavoriteNumber.length);//5myFavoriteNumber=7;console.log(myFavoriteNumber.length);//編譯時報錯//index.ts(5,30):errorTS2339:Property'length'doesnotexistontype'number'.上例中,第二行的myFavoriteNumber被推斷成了stringlength屬性不會報錯。而第四行的myFavoriteNumber被推斷成了numberlength屬性時就報錯了。參考\hAdvancedyps#nion\h()25聯(lián)合類型\h上一章:類型推論\h下一章:對象的類型26對象的類型對象的類型——接口在中,我們使用接口()來定義對象的類型。什么是接口在面向對象語言中,接口(而具體如何行動需要由類(\h中的接口是一個非常靈活的概念,除了可用于\h象簡單的例子interfacePerson{name:string;age:number;}letxcatliu:Person={name:'XcatLiu',age:25,};上面的例子中,我們定義了一個接口Person,接著定義了一個變量xcatliu,它的類型是Person。這樣,我們就約束了xcatliu的形狀必須和接口Person一致。接口一般首字母大寫。定義的變量比接口少了一些屬性是不允許的:27對象的類型interfacePerson{name:string;age:number;}letxcatliu:Person={name:'XcatLiu',};//index.ts(6,5):errorTS2322:Type'{name:string;}'isnotassignabletotype'Person'.//Property'age'ismissingintype'{name:string;}'.多一些屬性也是不允許的:interfacePerson{name:string;age:number;}letxcatliu:Person={name:'XcatLiu',age:25,website:'',};//index.ts(9,3):errorTS2322:Type'{name:string;age:number;website:string;}'isnotassignabletotype'Person'.//Objectliteralmayonlyspecifyknownproperties,and'website'doesnotexistintype'Person'.可見,賦值的時候,變量的形狀必須和接口的形狀保持一致??蛇x屬性有時我們希望不要完全匹配一個形狀,那么可以用可選屬性:28對象的類型interfacePerson{name:string;age?:number;}letxcatliu:Person={name:'XcatLiu',};interfacePerson{name:string;age?:number;}letxcatliu:Person={name:'XcatLiu',age:25,};可選屬性的含義是該屬性可以不存在。這時仍然不允許添加未定義的屬性:29對象的類型interfacePerson{name:string;age?:number;}letxcatliu:Person={name:'XcatLiu',age:25,website:'',};//examples/playground/index.ts(9,3):errorTS2322:Type'{name:string;age:number;website:string;}'isnotassignabletotype'Person'.//Objectliteralmayonlyspecifyknownproperties,and'website'doesnotexistintype'Person'.任意屬性有時候我們希望一個接口允許有任意的屬性,可以使用如下方式:interfacePerson{name:string;age?:number;[propName:string]:any;}letxcatliu:Person={name:'XcatLiu',website:'',};使用[propName:string]定義了任意屬性取string類型的值。需要注意的是,一旦定義了任意屬性,那么確定屬性和可選屬性都必須是它的子屬性:30對象的類型interfacePerson{name:string;age?:number;[propName:string]:string;}letxcatliu:Person={name:'XcatLiu',age:25,website:'',};//index.ts(3,3):errorTS2411:Property'age'oftype'number'isnotassignabletostringindextype'string'.//index.ts(7,5):errorTS2322:Type'{[x:string]:string|number;name:string;age:number;website:string;}'isnotassignabletotype'Person'.//Indexsignaturesareincompatible.// Type'string|number'isnotassignabletotype'string'.// Type'number'isnotassignabletotype'string'.上例中,任意屬性的值允許是string,但是可選屬性age的值卻是number,number不是string的子屬性,所以報錯了。另外,在報錯信息中可以看出,此時{name:'XcatLiu',age:25,website:''}的類型被推斷成了{[x:string]:string|number;name:string;age:number;website:string;}是聯(lián)合類型和接口的結合。只讀屬性有時候我們希望對象中的一些字段只能在創(chuàng)建的時候被賦值,那么可以用readonly定義只讀屬性:31對象的類型interfacePerson{readonlyid:number;name:string;age?:number;[propName:string]:any;}letxcatliu:Person={id:89757,name:'XcatLiu',website:'',};xcatliu.id=9527;//index.ts(14,9):errorTS2540:Cannotassignto'id'becauseitisaconstantoraread-onlyproperty.上例中,使用readonly定義的屬性id初始化后,又被賦值了,所以報錯了。只讀的約束存在于第一次給對象賦值的時候,而不是第一次給只讀屬性賦值的時候:32對象的類型interfacePerson{readonlyid:number;name:string;age?:number;[propName:string]:any;}letxcatliu:Person={name:'XcatLiu',website:'',};xcatliu.id=89757;//index.ts(8,5):errorTS2322:Type'{name:string;website:string;}'isnotassignabletotype'Person'.//Property'id'ismissingintype'{name:string;website:string;}'.//index.ts(13,9):errorTS2540:Cannotassignto'id'becauseitisaconstantoraread-onlyproperty.上例中,報錯信息有兩處,第一處是在對xcatliu進行賦值的時候,沒有給id賦值。第二處是在給xcatliu.id賦值的時候,由于它是只讀屬性,所以報錯了。參考\hInterf(\h中文版\h上一章:聯(lián)合類型\h下一章:數(shù)組的類型33數(shù)組的類型數(shù)組的類型在中,數(shù)組類型有多種定義方式,比較靈活?!割愋?方括號」表示法最簡單的方法是使用「類型+方括號」來表示數(shù)組:letfibonacci:number[]=[1,1,2,3,5];數(shù)組的項中不允許出現(xiàn)其他的類型:letfibonacci:number[]=[1,'1',2,3,5];//index.ts(1,5):errorTS2322:Type'(number|string)[]'isnotassignabletotype'number[]'.//Type'number|string'isnotassignabletotype'number'.// Type'string'isnotassignabletotype'number'.此時[1,'1',2,3,5]的類型被推斷為(number|string)[]類型和數(shù)組的結合。letfibonacci:number[]=[1,1,2,3,5];fibonacci.push('8');//index.ts(2,16):errorTS2345:Argumentoftype'string'isnotassignabletoparameteroftype'number'.數(shù)組泛型也可以使用數(shù)組泛型(ericArray<elemType>來表示數(shù)組:letfibonacci:Array<number>=[1,1,2,3,5];34數(shù)組的類型關于泛型,可以參考\h泛型用接口表示數(shù)組接口也可以用來描述數(shù)組:interfaceNumberArray{[index:number]:number;}letfibonacci:NumberArray=[1,1,2,3,5];NumberArray表示:只要index的類型是number,那么值的類型必須是numberany在數(shù)組中的應用一個比較常見的做法是,用any表示數(shù)組中允許出現(xiàn)任意類型:letlist:any[]=['XcatLiu',25,{website:'http://xcatliu.com'}];類數(shù)組類數(shù)組(Array-ikeObjectargumentsfunctionsum(){letargs:number[]=arguments;}//index.ts(2,7):errorTS2322:Type'IArguments'isnotassignabletotype'number[]'.//Property'push'ismissingintype'IArguments'.事實上常見的類數(shù)組都有自己的接口定義,如IArguments,NodeListHTMLCollection等:35數(shù)組的類型functionsum(){letargs:IArguments=arguments;}關于內置對象,可以參\h考參考\hBasicyesArr\h()\hInterfces#Indexab\h(\h上一章:對象的類型\h下一章:函數(shù)的類型36函數(shù)的類型函數(shù)的類型\h函數(shù)是JavaScript中的一等公民函數(shù)聲明在JavaScript中,有兩種常見的定義函數(shù)的方式nctDeclarationFuctionxression//函數(shù)聲明(FunctionDeclaration)functionsum(x,y){returnx+y;}//函數(shù)表達式(FunctionExpression)letmySum=function(x,y){returnx+y;};一個函數(shù)有輸入和輸出,要在pt中對其進行約束,需要把輸入和輸出都考慮到,其中函數(shù)聲明的類型定義較簡單:functionsum(x:number,y:number):number{returnx+y;}注意,輸入多余的(或者少于要求的)參數(shù),是不被允許的:37函數(shù)的類型functionsum(x:number,y:number):number{returnx+y;}sum(1,2,3);//index.ts(4,1):errorTS2346:Suppliedparametersdonotmatchanysignatureofcalltarget.functionsum(x:number,y:number):number{returnx+y;}sum(1);//index.ts(4,1):errorTS2346:Suppliedparametersdonotmatchanysignatureofcalltarget.函數(shù)表達式如果要我們現(xiàn)在寫一個對函數(shù)表達式(Expr這樣:letmySum=function(x:number,y:number):number{returnx+y;};這是可以通過編譯的,不過事實上,上面的代碼只對等號右側的匿名函數(shù)進行了類型定義,而等號左邊的mySum,是通過賦值操作進行類型推論而推斷出來的。如果需要我們手動給mySum添加類型,則應該是這樣:letmySum:(x:number,y:number)=>number=function(x:number,y:number):number{returnx+y;};38函數(shù)的類型在的類型定義中,=>用來表示函數(shù)的定義,左邊是輸入類型,需要用括號括起來,右邊是輸出類型。其中,=>在ES6中叫箭頭函數(shù),應用十分廣泛,可以參考\hES6中的箭頭函數(shù)接口中函數(shù)的定義我們也可以使用接口的方式來定義一個函數(shù)需要符合的形狀:interfaceSearchFunc{(source:string,subString:string):boolean;}letmySearch:SearchFunc;mySearch=function(source:string,subString:string){returnsource.search(subString)!==-1;}可選參數(shù)前面提到,輸入多余的(或者少于要求的)參數(shù),是不允許的。那么如何定義可選的參數(shù)呢?與接口中的可選屬性類似,我們用?表示可選的參數(shù):functionbuildName(firstName:string,lastName?:string){if(lastName){returnfirstName+''+lastName;}else{returnfirstName;}}letxcatliu=buildName('Xcat','Liu');letxcat=buildName('Xcat');需要注意的是,可選參數(shù)必須接在必需參數(shù)后面。換句話說,可選參數(shù)后面不允許再出現(xiàn)必須參數(shù)了:39函數(shù)的類型functionbuildName(firstName?:string,lastName:string){if(firstName){returnfirstName+''+lastName;}else{returnlastName;}}letxcatliu=buildName('Xcat','Liu');letxcat=buildName(undefined,'Xcat');//index.ts(1,40):errorTS1016:Arequiredparametercannotfollowanoptionalparameter.參數(shù)默認值在ES6中,我們允許給函數(shù)的參數(shù)添加默認值,會將添加了默認值的參數(shù)識別為可選參數(shù):functionbuildName(firstName:string,lastName:string='Liu'){returnfirstName+''+lastName;}letxcatliu=buildName('Xcat','Liu');letxcat=buildName('Xcat');此時就不受「可選參數(shù)必須接在必需參數(shù)后面」的限制了:functionbuildName(firstName:string='Xcat',lastName:string){returnfirstName+''+lastName;}letxcatliu=buildName('Xcat','Liu');letxcat=buildName(undefined,'Xcat');關于默認參數(shù),可以參考\hES6中函數(shù)參數(shù)的默認值40函數(shù)的類型剩余參數(shù)ES6中,可以使用...rest的方式獲取函數(shù)中的剩余參數(shù)(functionpush(array,...items){items.forEach(function(item){array.push(item);});}leta=[];push(a,1,2,3);事實上,items是一個數(shù)組。所以我們可以用數(shù)組的類型來定義它:functionpush(array:any[],...items:any[]){items.forEach(function(item){array.push(item);});}leta=[];push(a,1,2,3);\h注意,參數(shù)只能是最后一個參數(shù),關于rst參數(shù),可以參考ES6中的rest\h數(shù)重載重載允許一個函數(shù)接受不同數(shù)量或類型的參數(shù)時,作出不同的處理。比如,我們需要實現(xiàn)一個函數(shù)reverse123的時候,輸出反轉的數(shù)字321,輸入字符串'hello'的時候,輸出反轉的字符串'olleh'利用聯(lián)合類型,我們可以這么實現(xiàn):41函數(shù)的類型functionreverse(x:number|string):number|string{if(typeofx==='number'){returnNumber(x.toString().split('').reverse().join(''));}elseif(typeofx==='string'){returnx.split('').reverse().join('');}}然而這樣有一個缺點,就是不能夠精確的表達,輸入為數(shù)字的時候,輸出也應該為數(shù)字,輸入為字符串的時候,輸出也應該為字符串。這時,我們可以使用重載定義多個reverse的函數(shù)類型:functionreverse(x:number):number;functionreverse(x:string):string;functionreverse(x:number|string):number|string{if(typeofx==='number'){returnNumber(x.toString().split('').reverse().join(''));}elseif(typeofx==='string'){returnx.split('').reverse().join('');}}上例中,我們重復定義了多次函數(shù)reverse函數(shù)實現(xiàn)。在編輯器的代碼提示中,可以正確的看到前兩個提示。注意,ypeScript會優(yōu)先從最前面的函數(shù)定義開始匹配,所以多個函數(shù)定義如果由包含關系,需要優(yōu)先把精確的定義寫在前面。參考\hFunctions\h()\hFunctionsFyes\h()\hJS函數(shù)式編程指南\hES6中的箭頭函數(shù)\hES6中函數(shù)參數(shù)的默認值\hES6中的rest42函數(shù)的類型\h上一章:數(shù)組的類型\h下一章:類型斷言43類型斷言類型斷言類型斷言(ypeAssertion類型(即程序員對編譯器斷言)。語法<類型>值//或值as類型//在TSX語法(React的JSX語法的TS版)中必須用后一種例子:將一個聯(lián)合類型的變量指定為一個更加具體的類型\h之前提到過,當ypeScript不確定一個聯(lián)合類型的變量到底是哪個類型的時候,我們只能訪問此聯(lián)合類型的所有類型里共有的屬性或方法:functiongetLength(something:string|number):number{returnsomething.length;}//index.ts(2,20):errorTS2339:Property'length'doesnotexistontype'string|number'.//Property'length'doesnotexistontype'number'.而有時候,我們確實需要在還不確定類型的時候就訪問其中一個類型的屬性或方法,比如:44類型斷言functiongetLength(something:string|number):number{if(something.length){returnsomething.length;}else{returnsomething.toString().length;}}//index.ts(2,17):errorTS2339:Property'length'doesnotexistontype'string|number'.//Property'length'doesnotexistontype'number'.//index.ts(3,22):errorTS2339:Property'length'doesnotexistontype'string|number'.//Property'length'doesnotexistontype'number'.上例中,獲取something.length的時候會報錯。此時可以使用類型斷言,將something斷言成stringfunctiongetLength(something:string|number):number{if((<string>something).length){return(<string>something).length;}else{returnsomething.toString().length;}}類型斷言的用法如上,在需要斷言的變量前加上<Type>即可。類型斷言不是類型轉換,斷言成一個聯(lián)合類型中不存在的類型是不允許的:functiontoBoolean(something:string|number):boolean{return<boolean>something;}//index.ts(2,10):errorTS2352:Type'string|number'cannotbeconvertedtotype'boolean'.//Type'number'isnotcomparabletotype'boolean'.45類型斷言參考\hDeepDive/Assertion\hAdvancedyps#GuarsandDiferentatng(\h中文版\h上一章:函數(shù)的類型\h下一章:聲明文件46聲明文件聲明文件當使用第三方庫時,我們需要引用它的聲明文件。聲明語句假如我們想使用第三方庫,比如jQueryid是foo的元素:$('#foo');//orjQuery('#foo');但是在ypeScript中,我們并不知道$或jQuery是什么東西:jQuery('#foo');//index.ts(1,1):errorTS2304:Cannotfindname'jQuery'.這時,我們需要使用declare關鍵字來定義它的類型,幫助們傳入的參數(shù)類型對不對:declarevarjQuery:(string)=>any;jQuery('#foo');declare定義的類型只會用于編譯時的檢查,編譯結果中會被刪除。上例的編譯結果是:jQuery('#foo');聲明文件47聲明文件通常我們會把類型聲明放到一個單獨的文件中,這就是聲明文件://jQuery.d.tsdeclarevarjQuery:(string)=>any;我們約定聲明文件以.d.ts為后綴。然后在使用到的文件的開頭,用「三斜線指令」表示引用了聲明文件:///<referencepath="./jQuery.d.ts"/>jQuery('#foo');第三方聲明文件\h當然,Query的聲明文件不需要我們yn\hDefi。我們可以直接下載下來使用,但是更推薦的是使用工具統(tǒng)一管理第三方庫的聲明文件。\h社區(qū)已經(jīng)有多種方式引入聲明文件,不過ypeScript2.0推薦使用@types\h理@types的使用方式很簡單,直接用n安裝對應的聲明模塊即可,以jQu例:npminstall@types/jquery--save-dev可以在\h這個頁面搜索你需要的聲明文件。參考\hrtingDeclarationFiles\h()\hirect\h()48聲明文件\h上一章:類型斷言\h下一章:內置對象49內置對象內置對象JavaScript\h多,它們可以直接在中當做定義好了的類型。內置對象是指根據(jù)標準在全局作用域(ECMAScript和其他環(huán)境(比如DOMECMAScript的內置對象ECMAScript標準提供的內置對象有:Boolean、Error、Date、RegExp等。我們可以在中將變量定義為這些類型:letb:Boolean=newBoolean(1);lete:Error=newError('Erroroccurred');letd:Date=newDate();letr:RegExp=/[a-z]/;更多的內置對象,可以查看\hMN而他們的定義文件,則在\h核心庫的定義文件DOM和BOM的內置對象DOM和BO提供的內置對象有:Document、HTMLElement、Event、NodeList等。中會經(jīng)常用到這些類型:50內置對象letbody:HTMLElement=document.body;letallDiv:NodeList=document.querySelectorAll('div');document.addEventListener('click',function(e:MouseEvent){//Dosomething});它們的定義文件同樣在\h核心庫的定義文件ypecript核心庫的定義文件\h核心庫的定義文件中定義了所有瀏覽器環(huán)境需要用到的類型,并且是預置在ypeScript當你在使用一些常用的方法的時候,的工作了,比如:Math.pow(10,'2');//index.ts(1,14):errorTS2345:Argumentoftype'string'isnotassignabletoparameteroftype'number'.上面的例子中,Math.pow必須接受兩個number類型的參數(shù)。事實上Math.pow的類型定義如下:interfaceMath{/***Returnsthevalueofabaseexpressiontakentoaspecifiedpower.*@paramxThebasevalueoftheexpression.*@paramyTheexponentvalueoftheexpression.*/pow(x:number,y:number):number;}再舉一個D51內置對象document.addEventListener('click',function(e){console.log(e.targetCurrent);});//index.ts(2,17):errorTS2339:Property'targetCurrent'doesnotexistontype'MouseEvent'.上面的例子中,addEventListener方法是在ypeScr核心庫interfaceDocumentextendsNode,GlobalEventHandlers,NodeSelector,DocumentEvent{addEventListener(type:'click',listener:(ev:MouseEvent)=>any,useCapture?:boolean):void;}所以e被推斷成了MouseEventMouseEvent是沒有targetCurrent屬性的,所以報錯了。注意,ypeScript核心庫的定義中不包含Nde用ypeScript寫NodNode.s不是內置對象的一部分,如果想用y寫ode.s三方聲明文件:npminstall@types/node--save-dev參考\h內置對象\h核心庫的定義文件\h上一章:聲明文件\h下一章:進階52內置對象53進階進階本部分介紹一些高級的類型與技術,具體內容包括:\h類型別名\h字符串字面量類型\h元組\h枚舉\h類\h類與接口\h泛型\h聲明合并\h擴展閱讀上一章:內置對象\h下一章:類型別名54類型別名類型別名類型別名用來給一個類型起個新名字。簡單的例子typeName=string;typeNameResolver=()=>string;typeNameOrResolver=Name|NameResolver;functiongetName(n:NameOrResolver):Name{if(typeofn==='string'){returnn;}else{returnn();}}上例中,我們使用type創(chuàng)建類型別名。類型別名常用于聯(lián)合類型。參考\hAdvancedyps#Ali\h()\h上一章:進階\h下一章:字符串字面量類型55字符串字面量類型字符串字面量類型字符串字面量類型用來約束取值只能是某幾個字符串中的一個。簡單的例子typeEventNames='click'|'scroll'|'mousemove';functionhandleEvent(ele:Element,event:EventNames){//dosomething}handleEvent(document.getElementById('hello'),'scroll');//沒問題handleEvent(document.getElementById('world'),'dbclick');//報錯,event不能為'dbclick'//index.ts(7,47):errorTS2345:Argumentoftype'"dbclick"'isnotassignabletoparameteroftype'EventNames'.上例中,我們使用type定了一個字符串字面量類型EventNames三種字符串中的一種。注意,類型別名與字符串字面量類型都是使用type進行定義。參考\hAdvancedyps#Ali\h()\h上一章:類型別名\h下一章:元組56字符串字面量類型57元組元組數(shù)組合并了相同類型的對象,而元組(元組起源于函數(shù)編程語言(如F#簡單的例子定義一對值分別為string和number的元組:letxcatliu:[string,number]=['XcatLiu',25];當賦值或訪問一個已知索引的元素時,會得到正確的類型:letxcatliu:[string,number];xcatliu[0]='XcatLiu';xcatliu[1]=25;xcatliu[0].slice(1);xcatliu[1].toFixed(2);也可以只賦值其中一項:letxcatliu:[string,number];xcatliu[0]='XcatLiu';但是當直接對元組類型的變量進行初始化或者賦值的時候,需要提供所有元組類型中指定的項。letxcatliu:[string,number];xcatliu=['XcatLiu',25];58元組letxcatliu:[string,number]=['XcatLiu'];//index.ts(1,5):errorTS2322:Type'[string]'isnotassignabletotype'[string,number]'.//Property'1'ismissingintype'[string]'.letxcatliu:[string,number];xcatliu=['XcatLiu'];xcatliu[1]=25;//index.ts(2,1):errorTS2322:Type'[string]'isnotassignabletotype'[string,number]'.//Property'1'ismissingintype'[string]'.越界的元素當賦值給越界的元素時,它類型會被限制為元組中每個類型的聯(lián)合類型:letxcatliu:[string,number];xcatliu=['XcatLiu',25,'/'];上面的例子中,數(shù)組的第三項滿足聯(lián)合類型string|numberletxcatliu:[string,number];xcatliu=['XcatLiu',25];xcatliu.push('/');xcatliu.push(true);//index.ts(4,14):errorTS2345:Argumentoftype'boolean'isnotassignabletoparameteroftype'string|number'.//Type'boolean'isnotassignabletotype'number'.當訪問一個越界的元素,也會識別為元組中每個類型的聯(lián)合類型:59元組letxcatliu:[string,number];xcatliu=['XcatLiu',25,'/'];console.log(xcatliu[2].slice(1));//index.ts(4,24):errorTS2339:Property'slice'doesnotexistontype'string|number'.\h之前提到過,\h的屬性或方法。參考\hBasicyes\h()\h上一章:字符串字面量類型\h下一章:枚舉60枚舉枚舉枚舉(顏色限定為紅綠藍等。簡單的例子枚舉使用enum關鍵字來定義:enumDays{Sun,Mon,Tue,Wed,Thu,Fri,Sat};枚舉成員會被賦值為從0開始遞增的數(shù)字,同時也會對枚舉值到枚舉名進行反向映射:enumDays{Sun,Mon,Tue,Wed,Thu,Fri,Sat};console.log(Days["Sun"]===0);//trueconsole.log(Days["Mon"]===1);//trueconsole.log(Days["Tue"]===2);//trueconsole.log(Days["Sat"]===6);//trueconsole.log(Days[0]==="Sun");//trueconsole.log(Days[1]==="Mon");//trueconsole.log(Days[2]==="Tue");//trueconsole.log(Days[6]==="Sat");//true事實上,上面的例子會被編譯為:61枚舉varDays;(function(Days){Days[Days["Sun"]=0]="Sun";Days[Days["Mon"]=1]="Mon";Days[Days["Tue"]=2]="Tue";Days[Days["Wed"]=3]="Wed";Days[Days["Thu"]=4]="Thu";Days[Days["Fri"]=5]="Fri";Days[Days["Sat"]=6]="Sat";})(Days||(Days={}));手動賦值我們也可以給枚舉項手動賦值:enumDays{Sun=7,Mon=1,Tue,Wed,Thu,Fri,Sat};console.log(Days["Sun"]===7);//trueconsole.log(Days["Mon"]===1);//trueconsole.log(Days["Tue"]===2);//trueconsole.log(Days["Sat"]===6);//true上面的例子中,未手動賦值的枚舉項會接著上一個枚舉項遞增。如果未手動賦值的枚舉項與手動賦值的重復了,是不會察覺到這一點的:enumDays{Sun=3,Mon=1,Tue,Wed,Thu,Fri,Sat};console.log(Days["Sun"]===3);//trueconsole.log(Days["Wed"]===3);//trueconsole.log(Days[3]==="Sun");//falseconsole.log(Days[3]==="Wed");//true62枚舉上面的例子中,遞增到3的時候與前面的Sun的取值重復了,但是并沒有報錯,導致Days[3]的值先是"Sun""Web"覆蓋了。編譯的結果是:varDays;(function(Days){Days[Days["Sun"]=3]="Sun";Days[Days["Mon"]=1]="Mon";Days[Days["Tue"]=2]="Tue";Days[Days["Wed"]=3]="Wed";Days[Days["Thu"]=4]="Thu";Days[Days["Fri"]=5]="Fri";Days[Days["Sat"]=6]="Sat";})(Days||(Days={}));所以使用的時候需要注意,最好不要出現(xiàn)這種覆蓋的情況。手動賦值的枚舉項可以不是數(shù)字,此時需要使用類型斷言來讓查(譯出的)enumDays{Sun=7,Mon,Tue,Wed,Thu,Fri,Sat=<any>"S"};varDays;(function(Days){Days[Days["Sun"]=7]="Sun";Days[Days["Mon"]=8]="Mon";Days[Days["Tue"]=9]="Tue";Days[Days["Wed"]=10]="Wed";Days[Days["Thu"]=11]="Thu";Days[Days["Fri"]=12]="Fri";Days[Days["Sat"]="S"]="Sat";})(Days||(Days={}));當然,手動賦值的枚舉項也可以為小數(shù)或負數(shù),此時后續(xù)未手動賦值的項的遞增步長仍為163枚舉enumDays{Sun=7,Mon=1.5,Tue,Wed,Thu,Fri,Sat};console.log(Days["Sun"]===7);//trueconsole.log(Days["Mon"]===1.5);//trueconsole.log(Days["Tue"]===2.5);//trueconsole.log(Days["Sat"]===6.5);//true常數(shù)項和計算所得項枚舉項有兩種類型:常數(shù)項(membermmbe)。前面我們所舉的例子都是常數(shù)項,一個典型的計算所得項的例子:enumColor{Red,Green,Blue="blue".length};上面的例子中,"blue".length就是一個計算所得項。上面的例子不會報錯,但是如果緊接在計算所得項后面的是未手動賦值的項,那么它就會因為無法獲得初始值而報錯:enumColor{Red="red".length,Green,Blue};//index.ts(1,33):errorTS1061:Enummembermusthaveinitializer.//index.ts(1,40):errorTS1061:Enummembermusthaveinitializer.下面是常數(shù)項和計算所得項的完整定義,部分引用\h自冊-當滿足以下條件時,枚舉成員被當作是常數(shù):不具有初始化函數(shù)并且之前的枚舉成員是常數(shù)。在這種情況下,當前枚舉成員的值為上一個枚舉成員的值加1。但第一個枚舉元素是個例外。如果它沒有初始化方法,那么它的初始值為0枚舉成員使用常數(shù)枚舉表達式初始化。常數(shù)枚舉表達式是y子集,它可以在編譯階段求值。當一個表達式滿足下面條件之一時,它就是一64枚舉個常數(shù)枚舉表達式:數(shù)字字面量引用之前定義的常數(shù)枚舉成員(可以是在不同的枚舉類型中定義的)如果這個成員是在同一個枚舉類型中定義的,可以使用非限定名來引用帶括號的常數(shù)枚舉表達式+,-,~一元運算符應用于常數(shù)枚舉表達式+,-,*,/,%,<<,>>,>>>,&,|,^二元運算符,常數(shù)枚舉表達式做為其一個操作對象。若常數(shù)枚舉表達式求值后為Infinty所有其它情況的枚舉成員被當作是需要計算得出的值。常數(shù)枚舉常數(shù)枚舉是使用constenum定義的枚舉類型:constenumDirections{Up,Down,Left,Right}letdirections=[Directions.Up,Directions.Down,Directions.Left,Directions.Right];常數(shù)枚舉與普通枚舉的區(qū)別是,它會在編譯階段被刪除,并且不能包含計算成員。上例的編譯結果是:vardirections=[0/*Up*/,1/*Down*/,2/*Left*/,3/*Right*/];假如包含了計算成員,則會在編譯階段報錯:65枚舉constenumColor{Red,Green,Blue="blue".length};//index.ts(1,38):errorTS2474:In'const'enumdeclarationsmember

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論