TypeScript真香系列的內容將參考中文文檔,可是文中的例子基本不會和文檔中的例子重複,對於一些地方也會深刻研究。另外,文中一些例子的結果都是在代碼沒有錯誤後編譯爲JavaScript獲得的。若是想實際看看TypeScript編譯爲JavaScript的代碼,能夠訪問TypeScript的在線編譯地址,動手操做,印象更加深入。javascript
TypeScript的核心原則之一是對值所具備的結構進行類型檢查。 它有時被稱作「鴨式辨型法」或「結構性子類型化」。 在TypeScript裏,接口的做用就是爲這些類型命名和爲你的代碼或第三方代碼定義契約。能夠說接口的出現,可讓咱們在開發之中發現並避免許多問題的出現,提升咱們的開發效率。java
在面向對象編程中,接口是一種規範的定義,它定義了行爲和動做的規範。以下面的例子:git
interface IDo { work:string; time:number; } interface IMan { age:number; name:string; do:IDo; } let james: IMan = { name: 'james', age: 35, do: { work: 'player', time: 2020 } } james.name; //"james" james.do.work; //"player"
若是咱們在james中把name的類型寫成數字12,也就是number類型,或者沒有寫age。那麼就會出現錯誤提示。github
在咱們開發中,接口中的屬性有時候也不全都是必要的,在有些條件下存在,有些條件下又是不存在的。typescript
interface IMan { age?:number; name:string; } let james: IMan = { name:"james" }
一些對象屬性只能在對象剛剛建立的時候修改其值。編程
interface IMan { age:number; readonly name:string; } let james: IMan = { name:"james", age:35 } james.name = "mike"; // error: Cannot assign to 'name' because it is a read-only property.
在咱們可以肯定一個對象可能具備某些作爲特殊用途使用的額外屬性時,最佳的方式是可以添加一個字符串索引簽名。數組
interface IMan { age:number; readonly name:string; [propName: string]: any; } let james: IMan = { name:"james", age: 35, work:"player" }
函數也是對象,相似的咱們能夠用接口表示函數的類型。函數
interface IFunc { (x: string, y: string): string; } let func: IFunc = function(x: string, y: string){ return x + y; } func("1", "!"); // "1!"
對於函數類型的類型檢查來講,函數的參數名不須要與接口裏定義的名字相匹配。this
interface IFunc { (x: string, y: string): string; } let func: IFunc = function(a: string, b: string){ return a + b; } func("1", "!"); // "1!"
可用於數組和對象的約束。code
interface IMan { [index:number]:string } //數組 let man1: IMan; man1 = ["james", "wade", "bosh"]; //對象 let man2: Man; man2 = {1:"haha", 2:"666"}; console.log(man1); //["james", "wade", "bosh"] console.log(man2); //{1: "haha", 2: "666"}
TypeScript也可以用接口來明確的強制一個類去符合某種規定,能夠用implements來實現。
interface IMan { name:string; play(val:string):void; } class IFootballer implements IMan { name:string constructor(name:string){ this.name = name } play(val:string){ console.log(this.name + '踢'+ val) } } class IBasketballer implements IMan { name: string constructor(name:string){ this.name = name } play(val:string){ console.log(this.name + '打'+ val) } } var a = new Footballer('武磊') a.play("足球") //武磊踢足球 var b = new Basketballer ('姚明') b.play("籃球") //姚明打籃球
和咱們的類同樣,接口之間也能夠相互繼承。
interface IMan { name: string; } interface IPlayer extends IMan { types:string } class IFootballer implements IPlayer { name: string; types: string; constructor(name:string, types:string){ this.name = name; this.types = types } play(){ console.log(this.name+ "是" + this.types) } } let a = new Footballer("c羅", "足球運動員"); a.play(); //c羅是足球運動員
一個接口也能夠繼承多個接口,中間用逗號分隔。
interface IMan { name: string; } interface ICity { city:string; } interface IPlayer extends IMan,ICity { types:string }
混合類型
咱們可讓一個對象同時具備多種類型。
interface ICounter { (start: number): string; interval: number; reset(): void; } function getCounter(): ICounter { let counter = <ICounter>function (start: number) { }; counter.interval = 123; counter.reset = function () { }; return counter; } let c = getCounter(); c(10); c.reset(); c.interval = 5.0;
當接口繼承了一個類類型時,它會繼承類的成員但不包括其實現。 就好像接口聲明瞭全部類中存在的成員,但並無提供具體實現同樣。 接口一樣會繼承到類的private和protected成員。 這意味着當你建立了一個接口繼承了一個擁有私有或受保護的成員的類時,這個接口類型只能被這個類或其子類所實現(implement)。
當咱們有一個龐大的繼承結構時這頗有用,但要指出的是咱們的代碼只在子類擁有特定屬性時起做用。 這個子類除了繼承至基類外與基類沒有任何關係。
class Control { private state: any; } interface ISelectableControl extends IControl { select(): void; } class Button extends Control implements ISelectableControl { select() { } } class TextBox extends Control { select() { } } // 錯誤:「Image」類型缺乏「state」屬性。 class Image implements ISelectableControl { select() { } } //error class Location { }
https://github.com/zhongsp/Ty...
文中有些地方可能會加入一些本身的理解,如有不許確或錯誤的地方,歡迎指出~祝你們新年快樂,闔家辛福!但願前線的醫護人員健健康康,早日戰勝病毒!但願你們都健健康康!