# 05 TypeScript中的接口
# 接口的作用
在面向对象编程中,接口是一种规范定义,它定义了行为和动作规范,在程序设计中,接口起到一种限制和规范的作用。接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部状态数据,也不关心这些类方法的实现细节,只规定这些类必须提供某些方法,提供这些方法得类就可以满足实际需求。TypeScript中提供的接口类似于Java,但同时增加了更加灵活的接口类型,包括属性、函数、可索引和类等。
# 属性接口
# 对json的约束
function printLabel(labelledObj:{label:string}){
console.log(labelledObj.label);
}
let myObj = {size:10,label:'Size 10 Object'};
printLabel(myObj);//Size 10 Object
上面例子中,printLabel
函数传入一个对象(labelledObj
),并且该对象须有一个string
类型的属性字段label
# 对函数参数对象的属性约束
interface
关键字
interface FullName {
firstName: string;
secondName: string;// 注意需要以分号[;]结尾
}
function printName(name: FullName) {
//参数name必须有firstName和secondName属性字段
console.log(`${name.firstName} · ${name.secondName}`);
}
printName({
age:25, //报错
firstName: 'Steve',
secondName: 'Jobs'
});
报错。
类型“{ age: number; firstName: string; secondName: string; }”的参数不能赋给类型“FullName”的参数。
对象文字可以只指定已知属性,并且“age”不在类型“FullName”中。
printName({
firstName: 'Steve',
secondName: 'Jobs'
});//Steve · Jobs
正确 以上写法时,参数对象只能包含接口规定的参数以及对应数据类型,多余参数会报错。
var info= {
age:25,
firstName: 'Steve',
secondName: 'Jobs'
}
printName(info);//Steve · Jobs
以上写法也正确 参数对象单独定义,再传入printName
函数中,多余的参数不会报错,但接口规定的参数的属性字段数据类型依然必须保持一致。
# 对批量方法约束
printName
函数上面两种正确传参的写法,不论哪一种,其实现方法printName
的函数体内只能调用接口FullName
规定好的属性字段,多余的会报错。比如:
function printName(name: FullName) {
//参数name必须有firstName和secondName属性字段
console.log(`${name.firstName} · ${name.secondName} is ${name.age} years old.`);
}
其中在调用参数name
的age
属性时会报错:
类型“FullName”上不存在属性“age”。
# 可选属性接口
接口定义参数对象属性字段加上问好?
,代表可选属性字段。
interface PersonInfo {
firstName: string;
secondName: string;
age?: number;// ? 可选属性字段
}
function printPersonInfo(info: PersonInfo) {
if (info.age)
console.log(`${info.firstName} · ${info.secondName} is ${info.age} years old.`);
else
console.log(`How old is ${info.firstName} · ${info.secondName} ?`);
}
printPersonInfo({
age: 25,
firstName: 'Steve',
secondName: 'Jobs'
});//Steve · Jobs is 25 years old.
printPersonInfo({
firstName: 'Steve',
secondName: 'Jobs'
});//How old is Steve · Jobs ?
# 函数接口
对方法的传入参数以及返回值进行约束。可以批量约束。
// 举例:加密规范接口
interface encrypt {
(key: string, value: string): string
}
var md5: encrypt = function (key: string, value: string): string {
// 模拟结果
return `md5 ${key} ${value}`
}
console.log(md5("asdfgh","Sogrey"));//md5 asdfgh Sogrey
# 可索引接口
# 对数组的约束
回顾ts定义数组定义:
var arr: number[] = [11, 223];
var aar1: Array<string> = ['12', 'ased'];
// 约束数组成员只能是string类型
interface UseArr{
[index:number]:string
}
var ua:UseArr = ['aaa','sss'];
// var ua:UseArr = ['aaa','sss',1];//不能将类型“number”分配给类型“string”。
console.log(ua[1]);//sss
例子中定义的接口UseArr
约束数组成员只能是string类型,当你定义一个UseArr
类型的数组,其成员不全是string
就会报错,这是UseArr
接口约束的。
当然,如果将UseArr
修改为:
interface UseArr{
[index:number]:any
}
any
类型即不约束类型。
以上是定义接口对数组的约束,下面看下对对象的约束。
# 对对象的约束
interface UseObject{
[index:string]:string
}
var uo:UseObject = {
index:'001',
name:'Steve Jobs'
};
console.log(uo);//{index: "001", name: "Steve Jobs"}
这次接口UseObject
定义中index
为string
类型,表明是对象的index
属性类型为string
类型。
# 类类型接口
对类的约束,与抽象类相似。
interface Animals {
name: string;
eat(str: string): void;
}
class Cattle implements Animals {
name: string;
constructor(name: string) {
this.name = name;
}
eat() {// 没有传参 str 也没有报错,但eat方法必须实现
console.log(`${this.name} eat grass.`);
}
}
var cattle = new Cattle('Beitina');
cattle.eat();//Beitina eat grass.
定义类Cattle
必须要有name
属性和eat
方法,这是接口Animals
规定的,但是eat
方法没有传参str
也没有报错。
# 接口扩展
接口可以继承接口。
interface Animal1 {
eat():void;
}
interface Person1 extends Animal1{
work():void;
}
class Adult implements Person1{
eat(){
console.log(`要吃饭`);
}
work(){
console.log(`要工作`);
}
}
var adult = new Adult();
adult.work();//要工作
adult.eat();//要吃饭
以上例子中接口Person1
继承自Animal1
,类Adult
实现接口Person1
,则要全部实现接口Person1
以及接口Animal1
中所有的方法。
再扩展:
class Programmer {
name: string;
constructor(name: string) {
this.name = name;
}
coding(code: string) {
console.log(`在编程:${code}`);
}
}
class Adult extends Programmer implements Person1 {
eat() {
console.log(`要吃饭`);
}
work() {
console.log(`要工作`);
}
}
var adult = new Adult(`Sogrey`);
adult.work();//要工作
adult.eat();//要吃饭
adult.coding(`TypeScript`);//在编程:TypeScript
这次类Adult
继承自父类Programmer
,并且要实现接口Person1
。