TypeScript 基础之接口 (2)

559 阅读3分钟

这是我参与8月更文挑战的第4天,活动详情查看:8月更文挑战

接口

  • 接口用来描述使用这个接口的对象需要满足接口中定义的要求,*类型检查器不会检查这些属性的顺序。
  • 接口和类型在字面上很相似,接口规范了种类型,接口应该用大写字母开头,篇一种的大写字母的类型,String...,都是规范JS原生对象的接口。

定义接口 和 基本使用

  • 定义接口
    interface Value {
    key1: number,
    key2: number
    }
    interface ResValue {
        key1: string,
        key2: string
    }
    
  • 使用接口
    function numberToString(obj: Value): ResValue {
        return {key1: obj.key1.toString(), key2: obj.key2.toString()}
    }
    
    let val1: Value
    val1 = {
        key2: 15,
        key1: 'string' // 不能将类型“string”分配给类型“number”。
    }
    

使用接口规范函数

  • 接口用来规范函数,形参名不必相同,函数的参数会逐个进行检查,要求对应位置上的参数类型是符合的。
    // 定义
    interface NumberToStringFn {
        (prams1: number ): string
    }
    // 使用
    let numberToString: NumberToStringFn
    numberToString = function(number) {
        return number.toString()
    }
    

可索引类型

  • Javascript中对象的键实际上都是字符串类型,现在还有了Symbol类型,[]语法中使用对象,数子等都会自动调用toString()方法。
  • 可索引类型可以使用数字和字符串,可以同时使用,当时由于obj[1] = 1实际是obj['1'] = 1,所以字符串索引规定了全部的类型,数字索引仅规定了数字索引的类型,又因为obj[1]因满足obj['1'],所以数字索引的返回值类型必须是字符串索引类型的子类型,也就是能通过字符串索引规定类型的类型检查。
    interface Dic{
        [index: number]: number,
        [index: string]: Object,
    }
    
    let a: Dic 
    a[1] = 1
    a['2'] = new Object
    
  • 下面这个写发会报错原因是这种写发非索引操作,ts会认为接口中描述的是对象任意属性被定义为number 且 键必须是number类型
        let b: Dic = {  //  不能将类型“{ 1: number; '2': Object; }”分配给类型“Dic”。
                    //      属性“'2'”与索引签名不兼容。
                    //          不能将类型“Object”分配给类型“number”。
        1: 1,
        '2': new Object
    }
    
    
  • 可索引类型的只读设置和注意事项:设置后不可通过这种方式修改,如果只设置一种,在所束缚的是对象时,可通过字符串的方式修改,因为这里仅仅定义了数字类型索引。
    interface Dic{
        readonly [index: number]: string,
    }
    
    // let a: Dic 
    // a[1] = 1
    // a['2'] = new Object
    
    
    let a: Dic = ['0','1','2']
    let b: Dic = {0:'0',1:'2',2:'2'}
    
    b['0'] = '3'     // 无错误
    a['0'] = '3'     // 无错误
    b[0] = '3'       // 类型“Dic”中的索引签名仅允许读取。
    a[0] = '3'       // 类型“Dic”中的索引签名仅允许读取。
    

描述类

  • 检查类时只会检查实例部分,静态部分不会检查
    interface ClockInterface { // 用来描述类的接口
        ClassName: string, // 描述实例属性
        date: Date, // 描述实例属性
        getTime(): string //描述原型方法
        setTime(date: Date): void //描述原型方法
    }
    
    class Clock implements ClockInterface {
        ClassName: 'Clock'
        date: Date
        constructor(date: Date){ // 描述构造函数参数
            this.date = date || new Date()
        }
        getTime() {
            return this.date.toString()
        }
        setTime(date: Date) {
            this.date = date
        }
    
    }
    

继承接口

  • 可以某个接口 继承 另一个接口的所有描述
    interface A {
        a: string;
    }
    
    interface B {
        b: number;
    }
    
    interface C extends A, B {
        c: boolean;
    }
    
    let c: C
    c = {
        a: 'a',
        b: 1,
        c: true
    }
    

混合类型

  • 描述对象的不同使用方法时的类型检查
    interface _$$ {
        (fn?: Function) // 描述被调用时
        name: string
        getName: () => string
    }
    
    let $ = (function(): _$${
        const $ = function(fn){
            fn&&fn()
        }
        $.getName = function(){
            return $.name
        }
        $.name = '$' 
        return $
    })()
    
    $(function(){console.log('fn()')})
    $.getName()
    $.name = '$$$'
    

接口继承类

  • 接口会继承到类的 private 和 protected 成员
  • 继承类的接口类型只能用来约束这个类或这个类的子类
    class Control {
        private state: any;
    }
    
    interface SelectableControl extends Control { // 继承了 Control 类
        select(): void;
    }
    
    class Button extends Control implements SelectableControl {
        select() { }
    }
    
    class TextBox extends Control {
        select() { }
    }
    // 非接口继承的类使用这个接口 会出现 没有 Control 类的相关属性
    class Image implements SelectableControl {
        select() { }
    }