TypeScript--2.接口

之前介紹了一下TypeScript的基本配置和基本類型,接下來(lái)就開(kāi)始一些跟之前原生JS區(qū)別很大的內(nèi)容.

1.接口 interfaces

首先JS是沒(méi)有接口的這個(gè)概念的,但是接口還是在JAVA,OC里都是比較常見(jiàn)的概念.JAVA接口和OC的.h文件聲明接口,就是一些方法的集合,只有方法的聲明,沒(méi)有對(duì)應(yīng)方法的實(shí)現(xiàn),這些方法可能在不同的地方被實(shí)現(xiàn).在JS里只能模擬這種接口

2.鴨子類型 duck typing

動(dòng)態(tài)類型語(yǔ)言對(duì)變量類型的寬容給實(shí)際編碼帶來(lái)了很大的靈活性,無(wú)需檢測(cè),也不需要考慮變量是否擁有這個(gè)方法,隨意去調(diào)用任何的方法,這些便利都得益于鴨子類型.
鴨子類型這個(gè)概念源自一個(gè)諺語(yǔ)"當(dāng)看到一只鳥走起來(lái)像鴨子、游泳起來(lái)像鴨子阴孟、叫起來(lái)也像鴨子晌纫,那么這只鳥就可以被稱為鴨子",比如現(xiàn)在有兩個(gè)變量,一個(gè)是數(shù)組arr,另外一個(gè)變量也能能使用length,也能使用下標(biāo)來(lái)獲取值,那就可以認(rèn)為另外一個(gè)變量也是一個(gè)數(shù)組.
再舉一個(gè)例子:一只小老鼠被貓盯上了,情急之下永丝,它學(xué)了狗叫锹漱,貓撤了之后,小老鼠的媽媽不無(wú)感嘆的對(duì)它說(shuō):看吧慕嚷,我讓你學(xué)的這門兒外語(yǔ)多么重要啊.這里也使用了鴨子類型,當(dāng)貓抓老鼠的時(shí)候,老鼠學(xué)了狗叫,讓貓以為那是條狗,所以逃跑.
鴨子類型總得來(lái)說(shuō),關(guān)注的不是對(duì)象的類型本身哥牍,而是它是如何使用的.

3.JS的接口

通過(guò)鴨子類型實(shí)現(xiàn)接口,下面的代碼是在網(wǎng)上摘錄下來(lái)得,大家可以借鑒一下

//一: 接口類 Class Interface ==>實(shí)例化N多個(gè)接口  
/**  
  * 接口類需要2個(gè)參數(shù)  
  * 參數(shù)1: 接口的名字 (string)  
  * 參數(shù)2: 接受方法名稱的集合(數(shù)組) (array)  
*/  
var Interface = function(name , methods){  
    //判斷接口的參數(shù)個(gè)數(shù)  
    if(arguments.length != 2){  
        throw new Error('argument.length must be 2');  
 }  
    this.name = name;  
    this.methods = [];//定義一個(gè)內(nèi)置的空數(shù)組對(duì)象 等待接受methods里的元素(方法名字)  
    for(var i = 0, len = methods.length ;i < len; i++ ){  
        if(typeof methods[i] != 'string'){  
            throw new Error('methods.type must be string');  
         }  
          this.methods.push(methods[i]);  
      }
} 
// 二: 準(zhǔn)備工作:  
            // 1 實(shí)例化接口對(duì)象  
var CompositeInterface = new Interface('CompositeInterface' , ['add' , 'remove']);  
var FormItemInterface  = new Interface('FormItemInterface' , ['update','select']);  
//  CompositeImpl implements CompositeInterface , FormItemInterface  
// 2 具體的實(shí)現(xiàn)類   
var CompositeImpl = function(){  
                      
}   
// 3 實(shí)現(xiàn)接口的方法implements methods        
CompositeImpl.prototype.add = function(){  
 alert('add...');  
}  
CompositeImpl.prototype.update = function(){  
    alert('update...');  
}  
CompositeImpl.prototype.select = function(){  
    alert('select...');  
}  
CompositeImpl.prototype.remove = function(){  
     alert('remove...');  
}  
// 三:檢驗(yàn)接口里的方法  
// 如果檢驗(yàn)通過(guò) 不做任何操作 不通過(guò):瀏覽器拋出error  
// 這個(gè)方法的目的 就是檢測(cè)方法的  
Interface.ensureImplements = function(object){  
// 如果檢測(cè)方法接受的參數(shù)小于2個(gè) 參數(shù)傳遞失敗!  
if(arguments.length < 2){  
throw new Error('Interface.ensureImplements method constructor arguments must be  >= 2!');  
}  
// 獲得接口實(shí)例對(duì)象   
for(var i = 1; i < arguments.length;i++){  
    var instanceInterface = arguments[i]; 
    if(instanceInterface.constructor != Interface){  
      throw new Error('the arguments constructor not be Interface Class');  
    }         
   // 循環(huán)接口實(shí)例對(duì)象里面的每一個(gè)方法  
  for(var j=0;j < instanceInterface.methods.length;j++){  
        var methodName = instanceInterface.methods[j];  
    // object[key] 就是方法  
        if(!object[methodName] || typeof object[methodName] != 'function'){  
      throw new Error("the method name '" + methodName + "' is not found !");  
            }  
        }             
    }  
}
// 最后使用
var c1 = new CompositeImpl();

Interface.ensureImplements(c1,CompositeInterface,FormItemInterface);

c1.add(); 

4.TypeScript接口

TypeScript里,接口的作用就是為類型命名和代碼體統(tǒng)的一套契約,通過(guò)契約來(lái)判斷屬性是否存在,也可以認(rèn)為接口就是一個(gè)自定義的類型

interface LabelledValue { 
        label: string;
}
function printLabel(labelledObj: LabelledValue){
        console.log(labelledObj.label);
}
let myObj = {size: 10, label: "Size 10 Object"};
printLabel(myObj);

LabelledValue相當(dāng)于接口的名,在函數(shù)printLabel里,需要傳一個(gè)參數(shù),指定參數(shù)類型就是接口類型,就是LabelledValue類型,然后在函數(shù)里調(diào)用傳進(jìn)去對(duì)象的屬性,如果調(diào)用的是size,就會(huì)在文件里報(bào)錯(cuò),因?yàn)樵趯?duì)應(yīng)接口里,并沒(méi)有對(duì)應(yīng)屬性.接口里的屬性只要存在并且類型正確就可以.

5.可選屬性

在接口里,有些屬性不一定是必須的,有些屬性可能在某些條件下存在,這時(shí)候,為了避免在書寫,對(duì)這樣的屬性,在可選的屬性名字定的的后面加一個(gè)?符號(hào)

 interface SquareConfig { 
    color?: string; 
    width?: number;
}

6.只讀屬性

屬性的設(shè)置前,需要在屬性名前,用readonly來(lái)修飾屬性,通過(guò)這個(gè)類型構(gòu)建出來(lái)的對(duì)象,屬性值不允許變化

interface Point { 
    readonly x: number; 
    readonly y: number;
}
let p1: Point = { x: 10, y: 20 };
p1.x = 5; // error!

TypeScrip還有一個(gè)類型ReadonlyArray<T>,這個(gè)類型跟之前說(shuō)過(guò)的數(shù)組類型相似,只是所有對(duì)數(shù)組操作的方法都去掉了
readonly和const很相似,區(qū)別就在于做為變量使用的話用const
,若做為屬性則使用readonly.

7.函數(shù)類型

除了帶屬性的普通對(duì)象之外,接口也可以描述函數(shù)類型.

interface SearchFunc { 
        (source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) { 
        let result = source.search(subString); 
        if (result == -1) { 
            return false; 
        } else { 
            return true; 
        }
  }

接口里括號(hào)里是函數(shù)類型的參數(shù),但是參數(shù)名可以與接口里定義的名不匹配,冒號(hào)后是返回值的類型,這個(gè)類型要相同,否則編譯器會(huì)有警告

8.可索引的類型

這種接口的使用類似數(shù)組和對(duì)象,通過(guò)索引找到對(duì)應(yīng)值,接口支持兩種類型的索引,數(shù)字和字符串

// 數(shù)組元素是數(shù)字
interface StringArray {    
    [index: number]: number;
}
var myArray: StringArray = [1, 2];
console.log(myArray[0]);
// 數(shù)組是字符串
interface StringArray {   
    [index: number]: string;
}
var myArray: StringArray = ["Bob", "Fred"];
console.log(myArray[0]);

接口里方括號(hào)里index代表了索引,冒號(hào)代表索引類型,方括號(hào)外的number代表了取值的類型.如果接口里同時(shí)使用兩種類型的索引,數(shù)字索引的返回值必須是字符串索引返回值類型的子類型,字符串對(duì)應(yīng)的是父類,數(shù)字對(duì)應(yīng)的是子類

class Animal {    
    name: string;
}
class Dog extends Animal {    
    breed: string;
}
interface NotOkay {    
    [x: number]: Dog;    
    [x: string]: Animal;
}

這是正確的寫法,Dog這個(gè)類是Animal這個(gè)類的子類,所以number對(duì)應(yīng)的是子類Dog,string對(duì)應(yīng)的是父類Animal.當(dāng)使用 number來(lái)索引時(shí)喝检,JavaScript會(huì)將它轉(zhuǎn)換成string然后再去索引對(duì)象.
index的類型可以用來(lái)面熟常用的數(shù)組和dictionary (字典),需要所有屬性和返回值匹配

interface Dictionary {    
    [index: string]: number;    
    length: number;    // 可以嗅辣,length是number類型    
    name: string       // 錯(cuò)誤,`name`的類型不是索引類型的子類型
}

可以理解為number代表了string的子類型,所以不會(huì)報(bào)錯(cuò).最后還能將index設(shè)置成只讀,只需要加上readonly就可以了

9.類類型

類類型就是明確用來(lái)強(qiáng)制一個(gè)類去符合某種契約

interface ClockInterface { 
    currentTime: Date; 
    setTime(d: Date);
}
class Clock implements ClockInterface { 
    currentTime: Date; 
    setTime(d: Date) { 
        this.currentTime = d; 
    } 
    constructor(h: number, m: number) { }
}

聲明了一個(gè)接口,一個(gè)日期類型的屬性,還有一個(gè)setTime的方法,這個(gè)方法在類里實(shí)現(xiàn).在類里方法和屬性分為靜態(tài)部分和實(shí)例部分,對(duì)應(yīng)接口來(lái)講,只能對(duì)實(shí)例部分進(jìn)行類型檢查

interface ClockConstructor { 
    new (hour: number, minute: number);
}
class Clock implements ClockConstructor { 
    currentTime: Date; 
    constructor(h: number, m: number) { }
}

這里就會(huì)報(bào)錯(cuò),原因在于借口創(chuàng)建了一個(gè)類的實(shí)例,也就是new了一個(gè)對(duì)象,這個(gè)對(duì)象在創(chuàng)建的時(shí)候需要使用類的構(gòu)造器,也就是constructor,它就是類的靜態(tài)部分的內(nèi)容,接口檢測(cè)不到,所以會(huì)報(bào)錯(cuò).因此,在操作類的靜態(tài)部分,可以定義兩個(gè)接口

interface ClockConstructor { 
    new (hour: number, minute: number): ClockInterface;
}
interface ClockInterface { 
    tick();
}
function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface { 
  return new ctor(hour, minute);
}
class DigitalClock implements ClockInterface { 
    constructor(h: number, m: number) { } 
    tick() { 
        console.log("beep beep"); 
    }
}
let digital = createClock(DigitalClock, 12, 17);

通過(guò)兩個(gè)接口,ClockConstructor接口調(diào)用ClockInterface,ClockInterface接口調(diào)用tick方法,返回值就是一個(gè)新的對(duì)象,從而完成靜態(tài)部分內(nèi)容的調(diào)用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末挠说,一起剝皮案震驚了整個(gè)濱河市澡谭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌损俭,老刑警劉巖蛙奖,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異撩炊,居然都是意外死亡外永,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門拧咳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)伯顶,“玉大人,你說(shuō)我怎么就攤上這事骆膝〖礼茫” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵阅签,是天一觀的道長(zhǎng)掐暮。 經(jīng)常有香客問(wèn)我,道長(zhǎng)政钟,這世上最難降的妖魔是什么路克? 我笑而不...
    開(kāi)封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任樟结,我火速辦了婚禮,結(jié)果婚禮上精算,老公的妹妹穿的比我還像新娘瓢宦。我一直安慰自己,他們只是感情好灰羽,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布驮履。 她就那樣靜靜地躺著,像睡著了一般廉嚼。 火紅的嫁衣襯著肌膚如雪玫镐。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天怠噪,我揣著相機(jī)與錄音恐似,去河邊找鬼。 笑死舰绘,一個(gè)胖子當(dāng)著我的面吹牛蹂喻,可吹牛的內(nèi)容都是我干的葱椭。 我是一名探鬼主播捂寿,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼孵运!你這毒婦竟也來(lái)了秦陋?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤治笨,失蹤者是張志新(化名)和其女友劉穎驳概,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體旷赖,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡顺又,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了等孵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片稚照。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖俯萌,靈堂內(nèi)的尸體忽然破棺而出果录,到底是詐尸還是另有隱情,我是刑警寧澤咐熙,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布弱恒,位于F島的核電站,受9級(jí)特大地震影響棋恼,放射性物質(zhì)發(fā)生泄漏返弹。R本人自食惡果不足惜锈玉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望义起。 院中可真熱鬧嘲玫,春花似錦、人聲如沸并扇。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)穷蛹。三九已至土陪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間肴熏,已是汗流浹背鬼雀。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蛙吏,地道東北人源哩。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像鸦做,于是被迫代替她去往敵國(guó)和親励烦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 國(guó)家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說(shuō)閱讀 10,974評(píng)論 6 13
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理泼诱,服務(wù)發(fā)現(xiàn)坛掠,斷路器,智...
    卡卡羅2017閱讀 134,657評(píng)論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法治筒,類相關(guān)的語(yǔ)法屉栓,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法耸袜,異常的語(yǔ)法友多,線程的語(yǔ)...
    子非魚_t_閱讀 31,632評(píng)論 18 399
  • 九四年正月十六,十堰火車站人來(lái)熙嚷堤框,接踵摩肩域滥。我穿著校服,排隊(duì)買票胰锌,長(zhǎng)長(zhǎng)的隊(duì)伍從窗口一直延伸到大廳外面骗绕。隨著人流涌...
    玉妮閱讀 925評(píng)論 2 5
  • 大概連我自己都沒(méi)有料到,我會(huì)愿意冒著困意资昧,撇下暖和的被窩酬土,把這篇拖欠自己好幾天的東西寫下來(lái)。 今天的南昌降溫了格带,短...
    5609閱讀 461評(píng)論 5 4