接口的概念
接口的作用
用于约束对象、函数、类的契约(标准)
契约 (标准) 的形式:
API文档,弱标准,比如在开发之前,开发组长提前把一些开发文档给定义好了,但是在开发的过程中你可能不会按照文档的来进行规范,所以说API文档是弱标准
代码约束,强标准:在代码中使用的标准就是接口:interface
接口的使用与定义:接口约束和类型别名一样都不会参与运行
1、接口约束对象
interface 接口名字{ 属性:类型, name:sring, } let u: 接口名字={...} 2、定义函数方法
- 写法1: 直接写法
1、interface 方法名字{ (参数:类型):返回类型, };
2、也还有一种写法类似interface,就是使用类型别名 方法名字 {(参数:参数类型):返回类型}
如果两个{}里面没有任何成员名称则这个括号表示定界符 type 方法名字 = { (参数:类型):返回类型, }
- 写法2:在对象里面使用对象属性进行定义
interface User{ sayHell:()=>void,//写法1 sayBye():void//写法2 }
//这表示 该对象中必须要有sayHell这个方法并且没有返回值,否则报错 let u: User={ sayHell(){ console.log('hello world')} sayBye()(){ console.log('goodBye world')} }
2、接口继承 类似与类的继承的写法
class Son extends Father {}
使用interface例子,在继承的时候你可以取重新定义父级的属性,但是你不能修改父级的属性类型,
就如下面的例子 A对象的属性T1是string,当C对象想继承A对象,它可以自己也定义一个T1属性,
但是这个属性你不能和父级的属性类型不同,比如把C对象的T1属性改成number,结果是会报错的
所以既然父级有自己想要的属性,就不要多此一举,自己本身还去定义它,所以子接口不能覆盖父接口的成员和类型
interface A{
T1:string
}
interface B extends A{
T2:number
}
interface C extends A,B{
T1:string,
T3:boolean
}
let u:C ={
T1:"4",
T2:7,
T3:true
}
使用 类型别名 type,类型别名要想和继承一个就得使用组合的方式,使用“&”符号连接,叫做交叉类型,类型别名中 如果在C中去改变T1的类型,他不会报错,
但是在使用赋值是,你会发现T1的类型是把两个类型合并了,所以在赋值的时候你无法赋值
type A ={
T1:string
}
type B ={
T2:number
}
type C ={
T1:number,
T3:boolean
} & A & B
let u:C ={
T1:???,
T2:7,
T3:true
}
类型兼容性
1 定义:什么叫类型兼容
B->A,如果能完成赋值,则B和A类型兼容;TypeScript里的类型兼容性是基于结构子类型的。结构类型是一种只使用其成员来描述类型的方式
自己的理解就是 定义一个对象,你有这个对象的某一些特征,那你就可以兼容,
2 辨别法:鸭子辨型法(子结构辨型法)
目标类型需要一些特征,赋值的类型只要能满足该特征即可
3 类型兼容
基本类型:完全匹配,这没啥好说的
对象类型:鸭子辨型法
interface Duck {
sound:'嘎嘎嘎',//这是类型,不是赋值
swim():void,//会游泳
}
let person ={
name:'伪装成鸭子的人',
age:18,
// sound:'嘎嘎嘎',//这里有些小问题,在这里我们是属于赋值,而不是字面量类型,所以这里我们得用到“断言”,使用as
sound:'嘎嘎嘎' as "嘎嘎嘎", // "前面是数据" as "后面是类型"
swim(){
console.log(this.name + "正在游泳, 并发出了" +this.sound + "的声音")
}
}
//这是能正常赋值的,因为person 他有Duck的sound和swim这两个属性,就认为是一只鸭子
let duck: Duck =person
特殊情况:如果我们直接使用对象字面量赋值时候,就会报错。TS进行了更加严格的判断,因为Duck只有sound和swim这个两个属性,
所以只能有sound和swim这两个属性,其他的属性不能存在,存在则报错,我们只要把其余的实现删除就可以了
interface Duck {
sound:'嘎嘎嘎',//这是类型,不是赋值
swim():void,//会游泳
}
//这样写会报错
let duck: Duck ={
name:'伪装成鸭子的人',
age:18,
// sound:'嘎嘎嘎',//这里有些小问题,在这里我们是属于赋值,而不是字面量类型,所以这里我们得用到“断言”,使用as
sound:'嘎嘎嘎' as "嘎嘎嘎", // "前面是数据" as "后面是类型"
swim(){
console.log(this.name + "正在游泳, 并发出了" +this.sound + "的声音")
}
}
//正确的赋值
let duck: Duck ={
sound:'嘎嘎嘎' as "嘎嘎嘎", // "前面是数据" as "后面是类型"
swim(){
console.log("正在游泳, 并发出了" +this.sound + "的声音")
}
}