TypeScript知識點


1.1 Typescript 介紹

1.TypeScript 是由微軟開發的一款開源的編程語言,像后端 java、C#這樣的面向對象語言可以讓 js 開發大型企業項目。

2.TypeScript 是 Javascript的超級,遵循最新的 ES6、Es5 規范(相當於包含了es6、es5的語法)。TypeScript擴展了JavaScript的語法。

3.最新的 Vue 、React 也可以集成 TypeScript。

1.2 Typescript 安裝 編譯

安裝nodejs環境,用npm全局安裝typescript
npm install -g typescript 
Typescript文件后綴名為.ts,最后將編譯成js文件

Typescript手動編譯 => tsc + 文件名

// 將index.ts編譯成index.js tsc index.ts 

1.3 Typescript開發工具Vscode自動編譯.ts 文件

1.3.1 tsc --init 生成配置文件tsconfig.json

圖片描述

1.3.2 點擊菜單欄任務-運行任務(遇到錯誤使用快捷鍵ctrl + shift + b),點擊 tsc:監視-tsconfig.json 然后就可以自動生成代碼

圖片描述

二、Typescript數據類型

typescript中為了使編寫的代碼更規范,更有利於維護,增加了類型校驗

2.1 基礎類型

在typescript中主要給我們提供了以下數據類型:

布爾類型(boolean) 
數字類型(number) 
字符串類型(string) 
數組類型(array) 
元組類型(tuple) 
枚舉類型(enum) 
任意類型(any) 
null和undefined 
void類型 
never類型

相比於js,typescript中多了枚舉類型、任意類型、void類型和never類型

2.2 變量定義

寫ts代碼變量必須指定類型,指定類型后賦值必須為指定的類型,否則報錯

var flag:boolean = true flag = 123 // 錯誤,類型不一致

2.3 數據類型

布爾類型(boolean)

var flag:boolean = true flag = false // 正確 // flag=123; // 錯誤

數字類型(number)

var num:number = 123; num = 456; // 正確 // num='str'; //錯誤

字符串類型(string)

var str:string = 'this is ts'; str='haha'; //正確 // str=true; //錯誤

數組類型(array) ts中定義數組有兩種方式

// 第一種 var arr:number[] = [1, 2, 3] // 第二種 var arr2:Array<number> = [1, 2, 3]

元組類型(tuple)元素的類型不必相同,寫法和數組一樣

let arr:[number,string] = [123,'this is ts']

枚舉類型(enum)

用法:

enum 枚舉名{ 標識符[=整型常數], 標識符[=整型常數], ... 標識符[=整型常數], } 
enum Flag {success = 1,error = 2}; let s:Flag = Flag.success // 使用枚舉類型中的值 console.log('正確狀態',s) let f:Flag = Flag.error console.log('錯誤狀態',f)

任意類型(any)

為那些在編程階段還不清楚類型的變量指定一個類型

var number:any = 123 number = 'str' number = true

2.9 null 和 undefined

undefined:

{
    // 在js中,變量已聲明但未初始化為undefined var undefinedTest:number // console.log(undefinedTest) // 錯誤寫法,typescript報錯,賦值了才正確 // 在typescript中,已聲明未初始化的值要直接訪問的話類型需要定義為undefined var undefinedTest2:undefined console.log(undefinedTest2) // 正確寫法,輸出undefined } { // 可能是number類型 可能是undefined var undefinedTest3:number | undefined; console.log(num); }

null:

// null是一個空指針對象,undefined是未初始化的變量。因此,可以把undefined看作是空的變量,而null看作是空的對象 var nullTest:null nullTest = null // nullTest = {} // 錯誤,定義了類型是null,值必須為null

void類型

typescript中的void表示沒有任何類型,一般用於定義方法的時候方法沒有返回值。

// 表示方法沒有返回任何類型 function run(): void { console.log('run') } run()

never類型

表示的是那些永不存在的值的類型,例如異常
var a:never // a = 123 //錯誤寫法 a = (() => { throw new Error('錯誤'); })()

三、Typescript函數

內容概述: 函數的定義、可選參數、默認參數、剩余參數、函數重載、箭頭函數。

3.1.1 函數的定義

  • es5定義函數有函數聲明法和匿名函數法
// 法一:函數聲明法 function run():string { return 'run' } /** // 錯誤寫法 function run():string { return 123 } */ // 法二:匿名函數 var run2 = function ():string { return 'run2' } console.log('函數定義一', run()) console.log('函數定義二', run2())

3.1.2 ts中定義方法傳參

  • 函數傳參要指定數據類型
function paramFuc(name:string, age:number):string{ return `${name} --- ${age}` } console.log('函數傳參', paramFuc('dz', 20))

3.1.3 函數沒有返回值的方法用void

function voidFnc():void{ console.log('沒有返回值的方法用void') } voidFnc();

3.2 可選參數

  • es5里面方法的實參和行參可以不一樣,但是ts中必須一樣,如果不一樣就需要在可選參數后加?,這就是可選參數。
function electParam(name:string, age?:number):string { // 這里的age可傳可不傳,age就是可選參數 if(age){ return `${name} --- ${age}` }else{ return `${name} --- 年齡保密` } } console.log('可選參數', electParam('dz')) // 注意: 可選參數必須配置到參數的最后面 // 錯誤寫法:可選參數不在最后面 // function electParam2(name?: string, age: number): string { // ... // }

3.3 默認參數

  • es5里面沒法設置默認參數,es6和ts中都可以設置默認參數
// age為默認參數 function defaultParam(name:string, age:number = 20):String { return `${name} --- ${age}` } console.log('默認參數', defaultParam('dz'))

3.4 剩余參數

  • 當有很多參數時候或參數個數不確定,可以用三點運算符
// sum參數傳過來的是一個數組 function sum(...result: number[]): number { var sum = 0; for (var i = 0; i < result.length; i++) { sum += result[i]; } return sum; } console.log('剩余參數', sum(1, 2, 3, 4, 5, 6)); // a=1 b=2 其他參數為剩余參數 function sum2(a: number, b: number, ...result: number[]): number { var sum = a * b; for (var i = 0; i < result.length; i++) { sum += result[i]; } return sum; } console.log('剩余參數2', sum2(1, 2, 3, 4, 5, 6));

3.5 ts函數重載

同樣的函數,傳入不同的參數,實現不同的功能
  • java中方法的重載:重載指的是兩個或者兩個以上同名函數,但它們的參數不一樣,這時會出現函數重載的情況。
  • typescript中的重載:通過為同一個函數提供多個函數類型定義來實現多種功能的目的。
  • ts為了兼容es5 以及 es6 重載的寫法和java中有區別。
// es5中同名函數,后面會覆蓋前面的函數,ts中則不會 => 函數重載 function getInfo(name:string):string function getInfo(name:string, age:number):string function getInfo(name:any, age?:any):any { if(age) { return '姓名:' + name + '年齡:' + age }else{ return '姓名:' + name } } console.log(getInfo('dz')) console.log(getInfo('dz', 20)) // console.log(getInfo(20)) // 錯誤

3.6 箭頭函數

箭頭函數和es6中一樣

setTimeout(() => { console.log('箭頭函數') }, 1000);

四、Typescript中的類

4.1 es5中的類

內容概述:類的創建、靜態方法、繼承(對象冒充繼承,原型鏈繼承,對象冒充 + 原型鏈組合繼承)

es5中的面向對象、構造函數、原型與原型鏈本質可以看這個文檔http://caibaojian.com/javascr... , 個人覺得寫得很清晰。

4.1.1 類的創建

es5類在構造函數和原型鏈里都可以添加屬性和方法,原型鏈上的屬性會被多個實例所共享,而構造函數則不會。


function Person() { this.name = 'Ming' this.run = function() { console.log(this.name + '在運動') } } Person.prototype.sex = '男' // 原型鏈上的屬性會被多個實例所共享 Person.prototype.work = function() { console.log(this.name + '在工作') } var p = new Person() p.run() p.work() console.log(p.name) 

4.1.2 靜態方法

調用靜態方法不需要實例化

Person.getInfo=function(){ console.log('我是靜態方法'); } Person.getInfo(); 

4.1.3 實現繼承

對象冒充(或者叫構造函數繼承)繼承:可以繼承構造函數里面的屬性和方法,但是沒法繼承原型鏈上面的屬性和方法

原型繼承:可以繼承構造函數里面的屬性和方法,也可以繼承原型鏈上面的屬性和方法,但是實例化子類的時候沒法給父類傳參

下面是通過對象冒充 + 原型鏈組合繼承,解決了上面兩種繼承方式存在的問題


function Worker(name,age){ this.name=name; /*屬性*/ this.age=age; this.run=function(){ /*實例方法*/ alert(this.name+'在運動'); } } Worker.prototype.sex="男"; Worker.prototype.work=function(){ alert(this.name+'在工作'); } function Web(name,age){ Worker.call(this,name,age); // 對象冒充繼承,可以繼承構造函數里面的屬性和方法,實例化子類可以給父類傳參 } // Web.prototype = new Worker(); // 原型鏈繼承方法一:繼承Worker構造函數和原型上所有的方法和屬性 Web.prototype = Worker.prototype; //原型鏈繼承方法二:優化了方法一重復繼承構造函數屬性和方法的問題(本質可以看看http://caibaojian.com/javascript-object-5.html) var w = new Web('趙四',20); w.run(); w.work(); 

從上面可以看出,對象冒充繼承是在子類Web構造函數里面通過call方法繼承父類Worker的構造函數的屬性和方法;原型鏈繼承通過子類Web的原型對象等於父類Worker的原型對象來實現繼承;最后這兩種繼承的組合方式實現了完美繼承。

4.2 typescript中的類

內容概述: ts中類的定義、繼承、類修飾符、靜態屬性和靜態方法、多態、抽象類和抽象方法

4.2.1 ts中類的定義

ts中類的定義和es6類的定義一樣


class PersonDefine { name: string // 屬性,前面省略了public關鍵詞 constructor(name:string) { //構造函數 this.name = name } run():string { // 原型 return `${this.name}在運動` } } var define = new PersonDefine('類的定義') alert(define.run()) 

4.2.2 繼承

ts中繼承比es5簡單很多,用extends super實現繼承

class WebExtend extends PersonDefine { constructor(name:string) { super(name) // super繼承父類的構造函數,並向父類構造函數傳參 } work():string { return `${this.name}在工作` } } var extend = new WebExtend('繼承') alert(extend.run()) alert(extend.work()) 

4.2.3 ts類里面的修飾符

修飾符:typescript里面定義屬性的時候給我們提供了三種修飾符

  • public: 公有修飾符,在當前類里面、子類、類外面都可以訪問
  • protected:保護類型,在當前類里面、子類里面可以訪問,在類外部沒法訪問
  • private :私有修飾符,在當前類里面可以訪問,子類、類外部都沒法訪問

注意:屬性如果不加修飾符,默認就是公有修飾符


// 以private為例 class PersonPrivate{ private name:string; /*被private修飾的屬性 => 私有屬性*/ constructor(name:string){ this.name=name; } run():string{ return `${this.name}在運動` // 私有屬性只能在當前類里面可以訪問 } } class Web extends PersonPrivate{ constructor(name:string){ super(name) } work(){ // return `${this.name}在工作` // 報錯,子類不能訪問父類的私有屬性 } } var privateName = new PersonPrivate('private') alert(privateName.run()) // console.log(privateName.name) // 報錯,外部不能訪問類的私有屬性 

4.2.4 靜態屬性和靜態方法

為什么要用靜態屬性和靜態方法?jq里面的$.ajax就是用的靜態方法

function $(element) { return new Base(element) } function Base(element) { this.element = document.getElementById(element) this.css = function(arr, value) { this.element.style[arr] = value } } $('box').css('color','red') $.ajax = function() {} // 想要在$上使用方法怎么辦,用靜態方法 
ts中實現靜態屬性和靜態方法用static

class PersonStatic{ /*公有屬性*/ public name:string; constructor(name:string) { this.name=name; } /*實例方法(需要被實例化,所以為實例方法)*/ run(){ return `${this.name}在運動` } /*靜態屬性*/ static sex = '男' /*靜態方法,里面沒法直接調用類里面的屬性*/ static info(){ // return 'info方法' + this.name // 靜態方法不能調用本類的方法和屬性,可以調用靜態屬性 return 'info方法' + PersonStatic.sex } } console.log('靜態方法' + PersonStatic.info()) console.log('靜態屬性' + PersonStatic.sex) 

4.2.5 多態

父類定義一個方法不去實現,讓繼承它的子類去實現,每一個子類的該方法有不同的表現
  • 多態屬於繼承

比如定義一個父類Animal,里面的eat方法不去實現,讓子類Dog和Cat分別實現自己的eat方法


class Animal { name:string; constructor(name:string) { this.name=name; } eat(){ // eat方法繼承它的子類去實現 } } class Dog extends Animal{ constructor(name:string){ super(name) } eat(){ return this.name+'吃糧食' } } class Cat extends Animal{ constructor(name:string){ super(name) } eat(){ return this.name+'吃老鼠' } } 

4.2.6 抽象類和抽象方法

定義:用abstract關鍵字定義抽象類和抽象方法,抽象類中的抽象方法不包含具體實現並且必須在派生類(抽象類的子類)中實現
  • 抽象類:它是提供其他類繼承的基類,不能直接被實例化,子類繼承可以被實例化
  • abstract修飾的方法(抽象方法)只能放在抽象類里面
  • 抽象類和抽象方法用來定義標准(比如定義標准為:抽象類Animal有抽象方法eat,要求它的子類必須包含eat方法)

abstract class AnimalAbst{ public name:string; constructor(name:string){ this.name=name; } abstract eat():any; //抽象方法不包含具體實現並且必須在派生類中實現 run(){ console.log('其他方法可以不實現') } } // var a = new Animal() /*錯誤的寫法,抽象類不能被實例化*/ class DogAbst extends Animal{ //抽象類的子類必須實現抽象類里面的抽象方法 constructor(name:any){ super(name) } eat(){ return this.name + '吃糧食' } } var d = new DogAbst('小花花'); console.log('抽象類和抽象方法',d.eat()); 

五、TypesSript接口

接口定義:接口是對傳入參數進行約束;或者對類里面的屬性和方法進行聲明和約束,實現這個接口的類必須實現該接口里面屬性和方法;typescript中的接口用interface關鍵字定義。

接口作用:接口定義了某一批類所需要遵守的規范,接口不關心這些類的內部狀態數據,也不關心這些類里方法的實現細節,它只規定這批類里必須提供某些方法,提供這些方法的類就可以滿足實際需要。typescrip中的接口類似於java,同時還增加了更靈活的接口類型,包括屬性、函數、可索引和類等。

內容概述:接口分類:(屬性接口、函數類型接口、可索引接口、類類型接口),接口的繼承

5.1 接口分類

5.1.1 屬性接口

對傳入對象的約束(也就是對json的約束)

在了解接口之前,我們來看看函數傳入obj參數


function printLabel(labelInfo: {label:string}){ return labelInfo } // printLabel({name:'obj'}); //錯誤的寫法 console.log(printLabel({label: 'obj'})) 

和上面類似,由此引入屬性接口 => 對方法傳入參數進行約束

下面為屬性接口的例子,方法printFullName對傳入參數FullName(為對象)進行約束


interface FullName{
    firstName: string; // 注意;結束 secondName: string; age?: number // 接口的可選屬性用? } function printFullName(name:FullName) { // 傳入對象必須包含firstName和secondName,可傳可不傳age return name } var obj = { firstName:'小', secondName:'明', age: 20 } console.log(printFullName(obj)) 

屬性接口應用:原生js封裝ajax


interface Config{
    type: string; url: string; data?: string; dataType: string; } function ajax(config: Config) { var xhr = new XMLHttpRequest xhr.open(config.type, config.url, true) xhr.send(config.data) xhr.onreadystatechange = function() { if(xhr.readyState == 4 && xhr.status == 200) { if(config.dataType == 'json'){ console.log(JSON.parse(xhr.responseText)) }else{ console.log(xhr.responseText) } } } } ajax({ type: 'get', data: 'name=xiaoming', url: 'http://a.itying.com/api/productlist', dataType: 'json' }) 

5.1.2 函數類型接口

對方法傳入的參數以及返回值進行約束

interface encrypt{
    (key: string, value: string): string; // 傳入的參數和返回值的類型 } var md5:encrypt = function(key:string, value:string):string{ // encrypt對加密方法md5進行約束,同時md5方法的參數和返回值類型和encrypt要保持一致 return key + value } console.log(md5('name', '小明')) 

5.1.3 可索引接口

對索引和傳入參數的約束(一般用於對數組、對象的約束)

ts中定義數組:


var arr1:number[] = [1,2] var arr2:Array<string> = ['1', '2'] 

現在用接口來實現:


// 對數組的的約束 interface UserArr{ // 索引為number,參數為string [index:number]: string } var userarr:UserArr = ['a', 'b'] console.log(userarr) 

// 對象的約束 interface UserObj{ // 索引為string,參數為string [index:string]: string } var userobj:UserObj = { name: '小明', sex: '男' } console.log(userobj) 

5.1.4 類類型接口

對類的約束,和抽象類抽象有點相似

interface Animal{
    // 對類里面的屬性和方法進行約束 name:string; eat(str:string):void; } // 類實現接口要用implements關鍵字,必須實現接口里面聲明的方法和屬性 class Cat implements Animal{ name:string; constructor(name:string){ this.name = name } eat(food:string){ console.log(this.name + '吃' + food) } } var cat = new Cat('小花') cat.eat('老鼠') 

5.2 接口的繼承

和類的繼承一樣,用extends實現接口繼承

下面同時實現類的繼承和接口的繼承


interface Animal {
    eat(): void; } // 繼承Animal接口,則實現Person接口的類必須也實現Animal接口里面的方法 interface Person extends Animal { work(): void; } class Programmer { public name: string; constructor(name: string) { this.name = name; } coding(code: string) { console.log(this.name + code) } } // 繼承類並且實現接口 class Web extends Programmer implements Person { constructor(name: string) { super(name) } eat() { console.log(this.name + '吃') } work() { console.log(this.name + '工作'); } } var w = new Web('小李'); w.eat(); w.coding('寫ts代碼'); 

六、TypesSript泛型

泛型定義:泛型定義:泛型就是解決類、接口、方法的復用性,以及對不特定數據類型的支持(類型校驗)。ts中用T表示泛型。

泛型公式: <T>表示泛型,調用的時候指定T的數據類型

軟件工程中,我們不僅要創建一致的定義良好的API,同時也要考慮可重用性。 組件不僅能夠支持當前的數據類型,同時也能支持未來的數據類型,這在創建大型系統時為你提供了十分靈活的功能。

在像C#和Java這樣的語言中,可以使用泛型來創建可重用的組件,一個組件可以支持多種類型的數據。 這樣用戶就可以以自己的數據類型來使用組件。

內容概述:內容概述:函數的泛型、類的泛型、泛型接口

6.1 函數的泛型

傳入的參數類型和返回的參數類型可以指定

我們來看看函數用ts數據類型,想要同時返回string類型和number類型


function getData1(value:string):string{ return value; } function getData2(value:number):number{ return value; } 

這樣要寫不同的函數,不能按照需求返回不同類型數據,造成代碼冗余 => 由此引入泛型

<T>表示泛型,調用的時候指定T的數據類型

function dataT<T>(value:T):T{ // 傳入參數為T 返回值為T return value } dataT<number>(1) // 調用指定泛型為number類型,則傳入參數也必須為number類型 dataT<string>('string') function dataAny<T>(value:T):any{ return '傳入參數為T,任意類型返回值'; } dataAny<number>(123); // 參數必須是number dataAny<string>('這是一個泛型'); 

6.2 類的泛型

也是用<T>來實現類的泛型,new的時候指定T的數據類型

有個最小堆算法,需要同時支持返回數字和字符串兩種類型

使用泛型之前:只能在類的類部指定數據類型,實現需求還要寫一套string類型的類


class MinClass{ public list:number[]=[]; add(num:number){ this.list.push(num) } min():number{ var minNum=this.list[0]; for(var i=0;i<this.list.length;i++){ if(minNum>this.list[i]){ minNum=this.list[i]; } } return minNum; } } var m=new MinClass(); m.add(1); m.add(2); alert(m.min()); 

使用泛型之后:只用一套類來實現


class MinClassT<T>{ public list:T[]=[]; add(value:T):void{ this.list.push(value); } min():T{ var minNum=this.list[0]; for(var i=0;i<this.list.length;i++){ if(minNum>this.list[i]){ minNum=this.list[i]; } } return minNum; } } var m1=new MinClassT<number>(); /*實例化類 並且指定了類的T代表的類型是number*/ m.add(1); m.add(2); alert(m1.min()) var m2=new MinClassT<string>(); /*實例化類 並且指定了類的T代表的類型是string*/ m2.add('c'); m2.add('a'); alert(m2.min()) 

6.3 泛型接口

有一個函數類型接口


interface ConfigFn{
    (value:string):string;
}
var setData:ConfigFn = function(value:string):string{ return value } setData('name'); // setData(20); // 錯誤 

setData(20);寫法錯誤,想要傳入number類型的參數又要寫一個函數類型接口 => 用泛型接口

泛型接口有兩種寫法:


// 泛型接口定義方式一 interface ConfigFnOne{ <T>(value:T):T; } var setDataOne:ConfigFnOne = function<T>(value:T):T{ return value } // 既可以傳入string也可以傳入number類型參數 setDataOne<string>('name'); setDataOne<number>(20); 

// 泛型接口定義方式二 interface ConfigFnTwo<T>{ (value:T):T; } function setDataTwo<T>(value:T):T{ return value } var setDataTwoFn:ConfigFnTwo<string> = setDataTwo setDataTwoFn('name'); 

示例代碼請查看github,歡迎start https://github.com/dzfrontend...


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM