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阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容

  • 这是16年5月份编辑的一份比较杂乱适合自己观看的学习记录文档,今天18年5月份再次想写文章,发现简书还为我保存起的...
    Jenaral阅读 2,731评论 2 9
  • 当你最需要帮助的时候,请先去帮助有需要的人;当你最需要安慰的时候,请先去安慰伤心的人;当你最需要祝福的时候,请先去...
    王慧聪阅读 1,109评论 2 4
  • 明天是重阳节,苏菲昨天就看了日历,记着日子呢! 下班时回到家,爸爸告诉她,外婆在家一直念叨着,怎么今天重阳节没有人...
    飞呀飞me阅读 305评论 0 2
  • “我要去北京!”老人垂着头,固执地坚持着。 “不是不让您去,”老人的女儿在一边苦口婆心地劝,“现在天越来越冷了,您...
    梦藤阅读 311评论 0 0
  • 【家庭教育爱分享】 当我们从小就没有被父母耐心对待,投射了太多的焦虑,就容易对自己的孩子没有耐心,把这种焦虑不安和...
    上善若水4阅读 325评论 3 2