TypeScript学习日记-接口

153 阅读3分钟

一种规范的定义,行为和动作的规范,对批量方法约束

属性接口

对属性进行约束

// 当与需要对批量方法传参约束时
interface FullName {
    first: string,
    second: string
}
function printName(name: FullName) { console.log(name) } // 只要求需要name有first与second.可以有其他属性
printName({ second: '1', first: '2' }) // { second: '1', first: '2' } 不检查顺序
可选属性
// 可选属性
interface SelectFullName {
    first: string,
    second?: string // 可选
}
function printSelectName(name: SelectFullName) { console.log(name) } // 只要求需要name有first与second.可以有其他属性
printSelectName({ first: '2' }) // { first: '2' }
只读属性

一些对象属性只能在对象刚刚创建的时候修改其值

相比const, 当作变量时使用const, 而当作属性时使用readonly

interface Point {
    readonly x: number;
    readonly y: number;
}
额外类型检查
interface SquareConfig {
    color?: string;
    width?: number;
}
function createSquare(config: SquareConfig): any { return config }
// 这里color拼写成colour
// let mySquare = createSquare({ colour: "red", width: 100 }); //“colour”中不存在类型“SquareConfig”。是否要写入 color?
console.log(mySquare)

注意传入createSquare的参数拼写为colour而不是color。 在js里,这会默默地失败。ts会认为存在bug。 会经过额外属性检查,检查不到对于属性时, 会报错。

但是在接口添加属性,便不会报错

interface SquareConfig {
    color?: string;
    width?: number;
	[propName: string]: any;
}
function createSquare(config: SquareConfig): any { return config }
// 这里color拼写成colour
let mySquare = createSquare({ colour: "red", width: 100 });
console.log(mySquare) // { colour: 'red', width: 100 }
接口实现ajax的实例
interface Config {
    type: string;
    url: string;
    data?: string;
    dataType: string;
}

function ajax(config: Config) {
    var xhr = new XMLHttpRequest();
    xhr.open(config.type, config.url, true)
    xhr.send(config.data)
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4 && xhr.status === 200) {
            console.log('success')
        }
    }
}

函数类型接口

对方法传入的参数,以及返回值进行约束 批量约束. 类似一个只有参数列表和返回值类型的函数定义

interface encrypt {
    (key: string, value: string): string;
}

var md5: encrypt = function (key: string, value: string): string {
    return key + value
}
// 同时也不要求属性名相同
var md5: encrypt = function (k: string, v: string): string {
    return k + v
}

可索引类型接口

数组对象的接口约束(不常用)

// 数组约束
interface UserArr {
    [index: number]: string
}
var userArr: UserArr = ['aaa', 'bbb']

// 对象约束
interface UserObj {
    [index: string]: string
}
var userObj: UserObj = { name: '20' }

类接口

对类的约束 类似抽象类

interface Animal {
    name: string;
    eat(str: string): void
}

class Dog implements Animal {
    name: string;
    constructor(name: string) {
        this.name = name
    }
    eat() {
        console.log(this.name)
    }
}

当一个类实现了一个接口时,只对其实例部分进行类型检查。 constructor存在于类的静态部分,所以不在检查的范围内。

但是可以通过定义两个接口分别限制构造函数和方法实现. 在使用一个函数来生成需要类

interface DogConstructor {
    new(name: string, age: number): DogInterface;
}
interface DogInterface {
    eat();
}

function createDog(cons: DogConstructor, name: string, age: number): DogInterface {
    return new cons(name, age); // 这里限制了传入constructor的参数
}

class Dog implements DogInterface { // 这里限制了eat方法实现
    name: string
    constructor(name: string) { this.name = name }
    eat() {
        console.log(this.name + "eating");
    }
}

let d = createDog(Dog, '旺财', 2);
console.log(d) // Dog { name: '旺财' }
d.eat() // 旺财eating

接口继承

接口可以继承一个或多个接口

类可以在实现接口的同时继承类

interface Animal {
    eat(): void;
}
interface Person extends Animal {
    work(): void;
}

class Man implements Person {
    // 这里eat与work都需要继承
    eat() { console.log('eating') }
    work() { console.log('working') }
}

// 同也可以在实现接口的同时继承类
class Coder {
    code(): void { console.log('coding') }
}
class TSCoder extends Coder implements Person {
    // 这里eat与work都需要继承
    eat() { console.log('eating') }
    work() { console.log('working') }
}

同时, 接口可以继承类, 并在子类声明实现接口时也要继承接口继承的类, 否则会报错

class Animal {
    public name: string;
}

interface AnimalInterface extends Animal {
    eat(): void;
}
// 实现接口同时继承类
class Dog extends Animal implements AnimalInterface {
    eat() { }
}
// class Cat implements AnimalInterface { // 类型 "Cat" 中缺少属性 "name",但类型 "AnimalInterface" 中需要该属性。
//     eat() { }
// }
/// 或者直接再类中添加对应属性
class Cat implements AnimalInterface {
    eat() { }
    public name: string
}

但是当接口继承类的属性为private 和protected时. 直接再子类中声明类就不行了, 所以不推荐在子类中添加类

class Animal {
    private name: string;
}
// class Cat implements AnimalInterface { //  类型具有私有属性“name”的单独声明
//     eat() { }
//     private name: string
// }


class Animal {
    protected name: string;
}
// // 或者直接再类中添加对应属性
// class Cat implements AnimalInterface { //  属性“name”受保护,但类型“Cat”并不是从“Animal”派生的类
//     eat() { }
//     protected name: string
// }