TypeScript 接口

TypeScript
接口git

接口只讀屬性

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

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;   // 該句錯誤,不能進行賦值操做

出現錯誤,以下
json

建立不可修改的數組

// 定義一個接口
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

類型斷言很大程度上能夠規範類型app

函數類型的接口

// 定義一個函數類型的接口
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

編譯器會逐個檢查,若是通通正確,則編譯經過,不然編譯不經過ide

定義索引接口

// 定義索引接口
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類型的
函數

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

編譯一下出現錯誤ui

索引簽名依舊能夠設置爲只讀,此時能夠防止給索引賦值。使用關鍵字readonlythis

// 定義接口
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的類的時候,此時該接口只能被子類,或者該類使用。

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
相關文章
相關標籤/搜索