TypeScript 接口

TypeScript
接口

接口只讀屬性

使用關鍵字readonly定義只讀的接口屬性

interface Point {
    readonly x: number;
    readonly y: number;
}
// 定義一個接口
interface Point{
    readonly x: number;
    readonly y: number;
}

// 對接口賦值
let p1: Point = { x: 10, y: 20 };
p1.x = 5;   // 該句錯誤,不能進行賦值操作

出現錯誤,如下


image

創建不可修改的數組

image
// 定義一個接口
interface Point{
    readonly x: number;
    readonly y: number;
}

// 對接口賦值
let p1: Point = { x: 10, y: 20 };
//p1.x = 5; // 該句錯誤,不能進行賦值操作

let a: number[] = [1, 2, 3, 4, 5];
let ro: ReadonlyArray<number> = a;  // 設置為只讀的數組
ro[0] = 12; // 不可進行賦值。出現賦值錯誤

如果想要重新賦值,斷言重寫

當一個值有多個類型的時候,使用斷言重寫,確定一個新的類型

// 定義一個接口
interface Point{
    readonly x: number;
    readonly y: number;
}

// 對接口賦值
let p1: Point = { x: 10, y: 20 };
//p1.x = 5; // 該句錯誤,不能進行賦值操作

let a = [2, 3, 4, 5];
let ro: ReadonlyArray<number> = [2, 3, 4, 5];
//ro[0] = 12;   // 不可進行賦值
// 如果需要賦值,使用斷言重寫
a = ro as number[]; // 進行斷言重寫

// 對接口賦值
var p1 = { x: 10, y: 20 };
//p1.x = 5; // 該句錯誤,不能進行賦值操作
var a = [2, 3, 4, 5];
var ro = [2, 3, 4, 5];
//ro[0] = 12;   // 不可進行賦值
// 如果需要賦值,使用斷言重寫
a = ro; // 進行斷言重寫
//# sourceMappingURL=out.js.map

類型斷言很大程度上可以規范類型

函數類型的接口

// 定義一個函數類型的接口
interface SearchFunc {
    (source: string, subString: string): boolean;   // 定義一個函數類型的接口
}

// 使用這個接口
let mySearch: SearchFunc;
mySearch = (source:string,subString:string) => {
    let result = source.search(subString);  // 兩個字符串正則匹配
    return result > -1;
}
// 使用這個接口
var mySearch;
mySearch = function (source, subString) {
    var result = source.search(subString); // 兩個字符串正則匹配
    return result > -1;
};
//# sourceMappingURL=out.js.map

編譯器會逐個檢查,如果統統正確,則編譯通過,否則編譯不通過

定義索引接口

// 定義索引接口
interface StringArray {
    [index: number]: string;
}

let myArray: StringArray;   // 定義一個myArray的變量,類型為索引接口
myArray = ["Bob", "Fred"];

let myStr: string = myArray[0]; // 取第一個值

var myArray; // 定義一個myArray的變量,類型為索引接口
myArray = ["Bob", "Fred"];
var myStr = myArray[0]; // 取第一個值
//# sourceMappingURL=out.js.map

索引值內部必須全部為number類型的


image
// 定義接口,一個索引值類型的,其返回值也為索引類型的
interface NumberDictionary{
    [index: string]: number;
    length: number; // 可以設置length
    name: string;   // 錯誤索引值內部不能擁有string類型
}

編譯一下出現錯誤

索引簽名依舊可以設置為只讀,此時可以防止給索引賦值。使用關鍵字readonly

// 定義接口
interface NumberDictionary {
    readonly [index: number]: string;
}

// 初始化一個變量
let myArray: NumberDictionary = ["hello", "world"];

順帶配置一下配置文件

// tsconfig.json
{
    "compilerOptions": {
        "out": "built/out.js", 
        "sourceMap": true, 
        "target": "es5"
    }, 
    "files": [
        "greeter.ts"
    ]
}
// out.js
// 初始化一個變量
var myArray = ["hello", "world"];
//# sourceMappingURL=out.js.map
// 定義接口
interface NumberDictionary {
    readonly [index: number]: string;
}

// 初始化一個變量
let myArray: NumberDictionary = ["hello", "world"];

// 此時進行賦值為錯誤的
myArray[2] = "hello world";

類類型

明確一個類去符合一種接口

// 定義接口
interface ClockInterFace {
    currentTime: Date;
}

class Clock implements ClockInterFace { // 使用implements 關鍵字clock類符合接口clockInterFace
    currentTime: Date;
    constructor(h:number, m:number){
        // 定義構造函數
    }
}

// 注意在上方中并不會對靜態的,進行檢查。只會對非靜態的部分,即非構造函數部分進行檢查

var Clock = /** @class */ (function () {
    function Clock(h, m) {
        // 定義構造函數
    }
    return Clock;
}());
//# sourceMappingURL=out.js.map

如果配置成為es6即

{
    "compilerOptions": {
        "out": "built/out.js", 
        "sourceMap": true, 
        "target": "es6"
    }, 
    "files": [
        "greeter.ts"
    ]
}
class Clock {
    constructor(h, m) {
        // 定義構造函數
    }
}
//# sourceMappingURL=out.js.map

接口描述方法,類實現

interface ClockInterface {
    currentTime: Date;
    setTime(d: Date);   // 定義接口的方法
}

class Clock implements ClockInterface{
    currentTime: Date;  // 接口檢查的
    setTime(d:Date){    // 接口檢查的方法
        this.currentTime = d;
    }
    constructor(h:number, m:number){    // 接口不會檢查靜態的構造方法

    }
}
var Clock = /** @class */ (function () {
    function Clock(h, m) {
    }
    Clock.prototype.setTime = function (d) {
        this.currentTime = d;
    };
    return Clock;
}());
//# sourceMappingURL=out.js.map

關于構造函數的接口

構造函數屬于靜態的方法,當構造器定義了一個靜態的方法的時候。構造器只檢查動態的方法,并不會檢查動態的方法,故,下方的寫法編譯器不通過

interface ClockConstructor {
    new (hour: number, minuter: number);    // 定義構造函數的接口
};

class clock implements ClockConstructor {
    currenTime: Date;
    constructor(h:number, m:number){    // 接口限制的是此構造函數

    }
}interface ClockConstructor {
    new (hour: number, minuter: number);    // 定義構造函數的接口
};

class clock implements ClockConstructor {
    currenTime: Date;
    constructor(h:number, m:number){    // 接口限制的是此構造函數

    }
}interface ClockConstructor {
    new (hour: number, minuter: number);    // 定義構造函數的接口
};

class clock implements ClockConstructor {
    currenTime: Date;
    constructor(h:number, m:number){    // 接口限制的是此構造函數

    }
}interface ClockConstructor {
    new (hour: number, minuter: number);    // 定義構造函數的接口
};

class clock implements ClockConstructor {
    currenTime: Date;
    constructor(h:number, m:number){    // 接口限制的是此構造函數

    }
}interface ClockConstructor {
    new (hour: number, minuter: number);    // 定義構造函數的接口
};

class clock implements ClockConstructor {
    currenTime: Date;
    constructor(h:number, m:number){    // 接口限制的是此構造函數

    }
}interface ClockConstructor {
    new (hour: number, minuter: number);    // 定義構造函數的接口
};

class clock implements ClockConstructor {
    currenTime: Date;
    constructor(h:number, m:number){    // 接口限制的是此構造函數

    }
}

編譯

PS C:\Users\mingm\Desktop\ts> tsc
Active code page: 65001
greeter.ts:5:7 - error TS2420: Class 'clock' incorrectly implements interface 'ClockConstructor'.
  Type 'clock' provides no match for the signature 'new (hour: number, minuter: number): any'.

5 class clock implements ClockConstructor {
        ~~~~~

PS C:\Users\mingm\Desktop\ts>

出現錯誤

解決,既然不會對靜態的構造方法進行檢查,那就在創建一個接口,進行更進一步的靜態方法的檢查。
即,創建一個接口,返回一個接口,這樣就會對該構造方法進行檢查。

類似于類和父類的關系,子類,父類,超類,超類會返回一個類,會調用超類的構造方法,生成子類,此時在這個過程中會進行接口的檢查。

// 定義一個用于檢查構造函數的接口,該接口需要返回一個接口
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 {  // 下層接口
    constructo(h: number, m: number) { };
    tick(){
        console.log("!!!");
    }
}

// 定義一個類
class AnalogClock implements ClockInterface {
    constructor(h: number, m: number) { };
    tick(){
        console.log("!!!!!!!!");
    }
}

// 調用租函數,傳入一個類,返回一個對象
let digital = createClock(DigitalClock, 12, 17);
let analog = createClock(AnalogClock, 2, 4);

上方的核心在于創建了兩個接口,一個接口用于檢查父的內容,一個接口用于進行創建對象進行驗證。父的擁有一個函數,傳入一個類,并對其進行檢查。

// 創建一個函數,返回一個函數(該函數再次執行)
function createClock(ctor, hour, minute) {
    return new ctor(hour, minute); // 
}
// 定義一個類
var DigitalClock = /** @class */ (function () {
    function DigitalClock() {
    }
    DigitalClock.prototype.constructo = function (h, m) { };
    ;
    DigitalClock.prototype.tick = function () {
        console.log("!!!");
    };
    return DigitalClock;
}());
// 定義一個類
var AnalogClock = /** @class */ (function () {
    function AnalogClock(h, m) {
    }
    ;
    AnalogClock.prototype.tick = function () {
        console.log("!!!!!!!!");
    };
    return AnalogClock;
}());
// 調用租函數,傳入一個類,返回一個對象
var digital = createClock(DigitalClock, 12, 17);
var analog = createClock(AnalogClock, 2, 4);
//# sourceMappingURL=out.js.map
// 創建一個函數,返回一個函數(該函數再次執行)
function createClock(ctor, hour, minute) {
    return new ctor(hour, minute); // 此處類似于js中的閉包問題
}
// 定義一個類
class DigitalClock {
    constructo(h, m) { }
    ;
    tick() {
        console.log("!!!");
    }
}
// 定義一個類
class AnalogClock {
    constructor(h, m) { }
    ;
    tick() {
        console.log("!!!!!!!!");
    }
}
// 調用租函數,傳入一個類,返回一個對象
let digital = createClock(DigitalClock, 12, 17);
let analog = createClock(AnalogClock, 2, 4);
//# sourceMappingURL=out.js.map

繼承接口

類能繼承,那么接口也能繼承

// 接口
interface Shape {
    color: string;
}
// 一個繼承接口
interface Square extends Shape {
    sideLength: number; 
}

let square = {} as Square;  //類型斷言
square.color = "blue";
square.sideLength = 10; 

var square = {}; //類型斷言
square.color = "blue";
square.sideLength = 10;
//# sourceMappingURL=out.js.map

也可以進行從多個接口繼承,即創造出合成接口

interface Shape{
    color: string;
}

interface penStroke{
    penWidth: number;
}

// 從兩個接口繼承而來的接口
interface Square extends Shape, penStroke{
    sideLength: number;
}

let square = <Square>{};
square.color = "blue";
square.sideLength = 10;
square.penWidth = 5.0;
var square = {};
square.color = "blue";
square.sideLength = 10;
square.penWidth = 5.0;
//# sourceMappingURL=out.js.map

混合類型

對象既可為函數,又可為對象

interface Counter {
    (start: number): string;    // 函數
    interval: number;
    reset(): void;
}

// 下面將會書寫閉包
function getConter():Counter{   // 返回將會是一個接口類型的
    let counter = <Counter>function (start: number){};  // 類型斷言
    counter.interval = 123;
    counter.reset = () => { };
    return counter; // 返回一個函數
}

let c = getConter();
c(10);
c.reset();
c.interval = 5.0;
// 下面將會書寫閉包
function getConter() {
    var counter = function (start) { }; // 類型斷言
    counter.interval = 123;
    counter.reset = function () { };
    return counter; // 返回一個函數
}
var c = getConter();
c(10);
c.reset();
c.interval = 5.0;
//# sourceMappingURL=out.js.map

接口繼承類

接口繼承類時,會繼承類成員,但不包含其實現。
即,接口聲明了類中的成員,但并沒有提供具體的實現。
接口同樣會繼承private(私有的),和protected(對于本包和子同樣可見)

根據上述的說明,可以知道,當一個接口,繼承自擁有protected的類的時候,此時該接口只能被子類,或者該類使用。

image
class Control {
    private state: any; // 定義一個任何類型的私有屬性
}

// 定義一個接口,該接口繼承自Control
interface SelectableControl extends Control {
    select(): void;
}

// 定義一個子類,該類繼承自Control,并使用接口SelectableControl,由于是子類,可以使用SelectableControl接口
class Button extends Control implements SelectableControl {
    select() { };
}

// 定義一個子類該類繼承自Control
class TextBox extends Control {
    select(){}
}

// 定義一個Image類,該類不能使用SelectableControl接口
//class Image implements SelectableControl{

//}

// 和其余類沒有任何繼承關系的類
class Liaction {

}

es5 js如下

var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    }
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var Control = /** @class */ (function () {
    function Control() {
    }
    return Control;
}());
// 定義一個子類,該類繼承自Control,并使用接口SelectableControl,由于是子類,可以使用SelectableControl接口
var Button = /** @class */ (function (_super) {
    __extends(Button, _super);
    function Button() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    Button.prototype.select = function () { };
    ;
    return Button;
}(Control));
// 定義一個子類該類繼承自Control
var TextBox = /** @class */ (function (_super) {
    __extends(TextBox, _super);
    function TextBox() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    TextBox.prototype.select = function () { };
    return TextBox;
}(Control));
// 定義一個Image類,該類不能使用SelectableControl接口
//class Image implements SelectableControl{
//}
// 和其余類沒有任何繼承關系的類
var Liaction = /** @class */ (function () {
    function Liaction() {
    }
    return Liaction;
}());
//# sourceMappingURL=out.js.map
PS C:\Users\mingm\Desktop\ts> tsc
Active code page: 65001
PS C:\Users\mingm\Desktop\ts>

es6如下

class Control {
}
// 定義一個子類,該類繼承自Control,并使用接口SelectableControl,由于是子類,可以使用SelectableControl接口
class Button extends Control {
    select() { }
    ;
}
// 定義一個子類該類繼承自Control
class TextBox extends Control {
    select() { }
}
// 定義一個Image類,該類不能使用SelectableControl接口
//class Image implements SelectableControl{
//}
// 和其余類沒有任何繼承關系的類
class Liaction {
}
//# sourceMappingURL=out.js.map
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370

推薦閱讀更多精彩內容

  • 這是16年5月份編輯的一份比較雜亂適合自己觀看的學習記錄文檔,今天18年5月份再次想寫文章,發現簡書還為我保存起的...
    Jenaral閱讀 2,803評論 2 9
  • 當你最需要幫助的時候,請先去幫助有需要的人;當你最需要安慰的時候,請先去安慰傷心的人;當你最需要祝福的時候,請先去...
    王慧聰閱讀 1,177評論 2 4
  • 明天是重陽節,蘇菲昨天就看了日歷,記著日子呢! 下班時回到家,爸爸告訴她,外婆在家一直念叨著,怎么今天重陽節沒有人...
    飛呀飛me閱讀 315評論 0 2
  • “我要去北京!”老人垂著頭,固執地堅持著。 “不是不讓您去,”老人的女兒在一邊苦口婆心地勸,“現在天越來越冷了,您...
    夢藤閱讀 331評論 0 0
  • 【家庭教育愛分享】 當我們從小就沒有被父母耐心對待,投射了太多的焦慮,就容易對自己的孩子沒有耐心,把這種焦慮不安和...
    上善若水4閱讀 335評論 3 2