5. TS 中的接口的用途

141 阅读5分钟

一、ts 中接口 作用 和 类型

1. 接口的作用

接口的作用、在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范,在程序设计里面,接口起到了一种限制和规范的作用。接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部状态数据,也不关心这些类里方法的实现细节,它只规定这批类里必须提供某些方法,提供这些方法的类就可以满足实际需要。

2. 接口的类型

typeScript 中的接口类似于 java, 同时还增加了更灵活的接口类型,包含 属性函数可索引 等。

二、接口类型明细

1. 属性类型的接口

a. 属性类型的接口对传入的参数进行约束验证

错误写法:

image.png

正确写法:

// 这个表示 要传入一个 必须包含label 的 json 格式的数据
function box(labelInfo: {label: string}) {
    console.log(1)
}

let obj2 = {label: 'gg'}
box(obj2)      // 正确写法
b. 属性类型的接口: 对批量方法进行约束

属性类型的接口: 对批量方法进行约束

错误写法:

image.png 正确写法:

interface FullName{
    firstName:string;    // 注意, 这里要以【;】分号结束 
    secondName: string;
}

function getName(name:FullName) {
    // 必须传入对象 firstName  secondName
    console.log(`${name.firstName}${name.secondName}`) 
}

// 可进行批量约束
function getInfo(info:FullName) {
    // 必须传入对象 firstName  secondName

    console.log(`${info.firstName}${info.secondName}`)   // 正确写法
} 


// 正确写法   
getName({    // xl
    firstName: 'x',
    secondName: 'l'
})


// 最正确写法
let obj = {   // 传入的参数必须包含 firstName  secondName
    age: 20,
    firstName: 'x',
    secondName: 'l'
}
getName(obj)    // xl

// 最正确写法
let obj2 = {   // 传入的参数必须包含 firstName  secondName
    age: 20,
    firstName: 'g',
    secondName: 'g'
}
getInfo(obj2)    // gg
c. 属性类型接口: 参数传值顺序可以不用相同

属性类型接口: 参数传值顺序可以和接口定义的顺序不用相同但是一定要有接口中定义的属性,不然是会报错的

interface FullName{
    firstName:string;
    secondName: string;
}

function getName(name:FullName) {

}

// 参数传值顺序可以不用相同,但是一定要有接口中定义的属性,不然是会报错的。
getName({
    secondName: '壮',
    firstName: '小'
})
d. 属性类型接口: 可选属性

属性类型接口: 可选属性

interface FullName{
    firstName:string;
    secondName?: string;    // secondName? 问号表示 可选属性
}

function getName(name:FullName) {
    console.log(name.firstName + name.secondName)   // 小undefined
}


getName({
    firstName: '小'   
})

2. 函数类型接口

函数类型接口: 对方法传入的参数 及返回值进行约束, 同样可以进行批量约束\

()括号里表示是对方法传入的参数进行约束() 括号后面的是对返回值进行约束

interface secret{
    // ()括号里表示是对方法传入的参数进行约束, 括号后面的是对返回值进行约束
    (key:string,value:string):string;
}

const md5:secret = function(key:string, value:string):string{
    return key+value
}


const hn1:secret = function(key:string, value:string):string{
    return key+'--'+value
}

// 进行批量约束
alert(md5('xiao', 'gg'))   // xiaogg
alert(hn1('xiao', 'gg'))   // xiao--gg

3.可索引接口

可索引接口:通常用于对 数组 和对象 的约束

a. 可索引接口:数组的约束

可索引接口:数组的约束 :
[ ] 里表示数组的索引值为 Number 类型[ ] 后面的 string 表示数组的每一项元素都必须是 string 类型。

错误写法:

image.png

正确写法:

interface UseArr {
    // [] 里表示数组的索引值为 Number 类型,[] 后面的 string 表示数组的每一项元素都必须是 string 类型。
    [index:number]:string;
}

// 正确写法:
let arr2:UseArr = ['xl', 'gg']
b. 可索引接口:对象的约束

可索引接口:对象的约束
[ ] 里表示对象的索引值(也就是属性名)为 string 类型[ ] 后面的 string 表示对象的每一项属性值都必须是 string 类型

错误写法:

image.png

正确写法:

interface UseObj{
    // [] 里表示对象的索引值为 string 类型,[] 后面的 string 表示对象的每一项属性值都必须是 string 类型。
    [index:string]:string;
}

// 正确写法
let obj2:UseObj = { name: 'xl'} 

4. 类类型接口

类类型接口:对类的约束, 和抽象类有点相似
通过关键字 implements 来对类进行约束

interface Animal{
    // 创建的类必须要有 数据类型为 string 的 name 属性
    name:string;
    // 创建的类必须要有 eat 方法,eat 方法中可传入一个 数据类型为 string 的参数。void 表示  eat 方法 且没有返回值 
    eat(str:string):void;
}

// 通过关键字 implements 来对类进行约束
class Dog implements Animal{
    name: string;
    constructor(name:string) {
        this.name = name;
    }
    eat() {
        console.log(this.name + '吃东西')
    }
}
let d = new Dog('小狗')
console.log(d.eat())   // 小狗吃东西


class Cat implements Animal{
    name: string;
    constructor(name:string) {
        this.name = name;
    }

    eat(food:string) {
        console.log(this.name +"吃"+ food )
    }
}
let c = new Cat('小猫')
console.log(c.eat('老鼠'))   // 小猫吃老鼠

5. 接口扩展

接口扩展:接口可以继承接口

示例一:

通过类中的类型接口的扩展(接口继承接口,它需要写全继承来的属性和方法)

interface Animal{
    eat():void
}

// Person 接口继承 Animal 这个接口
interface Person extends Animal {
    work():void
}


class Web implements Animal{
    name:string;
    constructor(name:string) {
        this.name = name;
    }
    // 通过类中的类型接口的扩展(接口继承接口,它需要写全继承来的属性和方法)
    eat() {
        console.log(this.name + '吃东西')
    }
    work() {
        console.log(this.name + '在工作')
    }
}

let w = new Web('果果')
w.eat()  // 果果吃东西
w.work()  // 果果在工作

示例二:

接口可以继承接口,并且可以继承父类

interface Animal{
    eat():void;
}

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

class Program {
    name:string;

    constructor(name:string) {
        this.name = name;
    }

    codeing(doing:string) {
        console.log(this.name + doing)
    }
}

// 这个表示继承了父类Program 并且是遵循 Person 这个接口来定义类的
class Web extends Program implements Person{
    constructor(name:string) {
        super(name)
    }

    eat() {
        console.log(this.name + 'eat')
    }

    work() {
        console.log(this.name + 'work')
    }
}
let w = new Web('果果')
w.eat()  // 果果eat

w.work()  // 果果work

w.codeing('玩')   // 果果玩