接口:
接口设置的限制,实现的接口同样存在
接口实现为鸭式结构,及长得像就符合,所以接口可以约束对象和类
interface xx{
属性名:类型;
readonly 属性名:类型; 数据只读不可更改
属性名?:类型; 属性可实现可不实现
[propName:属性名类型]:类型; 可以追加指定类型属性,任意类型值改为any
方法名():类型; 定义约束方法
}
其中:
(1)接口中可以使用其他接口作为约束条件
(2)同名接口或同名类会自动混合约束
interface Foo {
x: number;
}
// ... elsewhere ...
interface Foo {
y: number;
}
let a: Foo = ...;
console.log(a.x + a.y); // OK
这同样作用于类:
class Foo {
x: number;
}
// ... elsewhere ...
interface Foo {
y: number;
}
let a: Foo = ...;
console.log(a.x + a.y); // OK
1、接口约束函数
函数的参数名不需要与接口里定义的名字相匹配
interface xx{
(参数:类型):返回类型
}
const fun:xx=(参数)=>{
return 返回类型
}
2、接口充当数组和索引签名(约束接口中的约束类型和变量中新增加的属性的类型)
interface arr4{
[index:number]:类型; 索引为数值,元素为指定类型的数组
}
let arr5:arr4=[1,2,3];
(1)索引签名(使得接口中的约束类型和变量的约束都要满足索引签名格式)
interface obj{
[index:索引类型]:值类型;
readonly [index: number]: string; 只读索引签名
接口中的其他键值对都要满足索引签名
如:
length: number;
}
(2)索引签名和数组区别
没有数组的方法或属性
使用数组的方法或属性:
方式一:类型断言
方式二:在定义索取签名时添加需要的属性或方法
interface f{
[index:number]:number;
length:number;
pop(): number|undefined;
}
(3)定义递归类型的嵌套解构,只能在属性中使用
如:定义嵌套的css
interface NestedCss{
color?:string;
next?:{
[cssName:string]:NestedCss
}
}
(4)索引签名混用:
interface obj{
[index:string]:值类型;
[index:number]:值类型; 数字索引的值类型必须是字符串索引值类型的子类型/相同类型
如:
[index: string]: any/父类;
[index: string]: number/子类;
}
例:
interface obj{
[index:string]:number; 接口中的其他约束都必须尊重该格式,以及约束的变量添加的新属性也要遵循该格式
length: number;
}
let s:obj={
length:1,
num:2, 所有属性都要满足索引签名格式
}
3、接口约束对象
let x:xx={
实现接口中的属性
属性名:值;
...
}
4、接口约束类(必须实现里面的属性和方法,可添加额外属性和方法)
class x implements xx{
实现接口中的属性
属性名:类型=值;
...
必须实现接口中的除了非必要属性以外的属性,以及实现的属性不能用private和protected修饰,因为接口中的属性是公有的
}
let y:xx=new x();
let y:x=new x();
如:
interface ClockInterface {
currentTime: Date;
setTime(d: Date);
}
class Clock implements ClockInterface {
currentTime: Date;
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m: number) { }
}
5、接口可以多继承,继承多个接口
interface x extends x1,x2{} 则x内含有x1和x2的约束条件
如果继承的接口是个泛型接口,需要实现泛型或者扩展泛型
实现泛型:interface x extends xx<类型>{...}
扩展泛型:interface x<T> extends xx<T>{...}
6、交叉接口,类似继承,会取交叉接口的并集
接口1&接口2
7、接口继承类
类定义会创建两个东西:类的实例类型和一个构造函数.因为类可以创建出类型,所以你能够在允许使用接口的地方使用类。
class Point {
x: number;
y: number;
}
其中:
类中的成员有private和protected修饰时,只能这个类或其子类中实现
例外:
如果类中属性有private修饰符
约束的类extends Point implements point3d,就无需实现类的属性包括private等修饰的属性,因为继承已经包含了这些属性
interface Point3d extends Point {
z: number;
}
let point3d: Point3d = {x: 1, y: 2, z: 3};
class C extends Point implements point3d{
z!: number;
无需实现类的属性包括private等修饰的属性,因为继承已经包含了这些属性
但如果再次实现,可以覆盖掉约束中protected/public的属性定义(即可以改写protected修饰符等),private只能在本类中调用,故不能再次覆盖
}
8、接口中的函数重载:
(1)相同接口合并函数重载的顺序
拥有字面量的函数优先->后面的接口顺序在前->写在最前面的函数优先
interface A{
foo(bar: number): number;//4
foo(bar: string): string;//5
foo(bar: 'a'): string;//2
}
interface A{
foo(bar: number): number[]; //3
foo(bar: 'b'): string;//1
}
(2)在实现时函数必须是比重载函数更宽泛的类型
interface A{
foo(bar: number): number;
foo(bar: string): string;
}
let a: A = {
foo(s:any) {
return s;
}
}
9、声明合并,会添加到类的原型对象上
class F{} 也可以是同名方法、变量
interface F { 会为类添加一个name属性
name:string
}
const f = new F();
f.name;
代码示例:
interface Person{
name:string;
age?:number; //?代表非必须项,不加'?'则接口实例就必须添加,不能多写
}
let jef:Person={
name:'jeff'
}
interface Stu{
readonly name:string; //设置只读属性
age?:number;
[propName:string]:any; //设置可以追加任意属性,属性名为string类型
}
let s:Stu={
name:'jeff',
age:18,
sex:'female'
}
//实现接口,接口的做限制类中同样存在
class Ssr implements Stu{
name:string='jack';
age:number=12;
constructor(ages:string){
}
}