接口是ts的核心之一,它的作用就是先约定好,再在定义的地方检查各种数据结构。
一、鸭子辩型法
鸭式辨型:像鸭子一样走路、游泳和嘎嘎叫的鸟就是鸭子。如下:
interface Duck {
walkLikeDuck(): any
swim(): any
gaga(): any
}
class Animal {
walkLikeDuck() {
console.log('look!, I walk like a duck.')
}
swim() {
console.log('YES! I can swim very well.')
}
gaga() {
console.log('gaga')
}
}
let duck: Duck = new Animal()
console.log(duck);
二、初识
理解为将函数、变量定义等等中的数据检查,抽离出来,成为接口。
三、可选属性(“option bags”模式)
与普通的接口定义差不多,只是在可选属性名字定义的后面加一个?
符号。
interface SquareConfig {
color?: string;
width?: number;
}
四、只读属性
一些对象属性只能在对象刚刚创建的时候修改其值。 你可以在属性名前用 readonly
来指定只读属性:
interface Point {
readonly x: number;
readonly y: number;
}
TypeScript具有ReadonlyArray<T>
类型,数组创建后再也不能被修改。
ReadonlyArray
赋值到一个普通数组也是不可以的。 但是你可以用类型断言重写。
a = ro as number[];
五、额外的属性检查
对象字面量会被特殊对待而且会经过 额外属性检查,当将它们赋值给变量或作为参数传递的时候。 如果一个对象字面量存在任何“目标类型”不包含的属性时,你会得到一个错误。
interface SquareConfig {
color?: string;
width?: number;
}
function createSquare(config: SquareConfig): { color: string; area: number } {
// ...
}
let mySquare = createSquare({ colour: "red", width: 100 });
// 类型“{ colour: string; width: number; }”的参数不能赋给类型“SquareConfig”的参数。
// 对象文字只能指定已知的属性,但“colour”中不存在类型“SquareConfig”。是否要写入 color?ts(2345)
可以使用类型断言来绕开检查:
let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig);
索引签名:
定义除已确定属性外的任意数量的其他额外属性。
interface SquareConfig {
color?: string;
width?: number;
[propName: string]: any;
}
六、函数类型
包含有参数列表和返回值类型的函数定义。
interface SearchFunc {
(source: string, subString: string): boolean;
}
七、索引类型
可索引类型具有一个 索引签名,它描述了对象索引的类型,还有相应的索引返回值类型。
interface StringArray {
[index: number]: string;
}
let myArray: StringArray;
myArray = ["Bob", "Fred"];
let myStr: string = myArray[0];
TypeScript支持两种索引签名:字符串和数字。 可以同时使用两种类型的索引,但是数字索引的返回值必须是字符串索引返回值类型的子类型。 这是因为当使用 number
来索引时,JavaScript会将它转换成string
然后再去索引对象。 也就是说用 100
(一个number
)去索引等同于使用"100"
(一个string
)去索引,因此两者需要保持一致。
class Animal {
name: string;
}
class Dog extends Animal {
breed: string;
}
// 错误:使用数值型的字符串索引,有时会得到完全不同的Animal!
interface NotOkay {
[x: number]: Dog;
[x: string]: Animal;
}
八、类类型
明确的强制一个类去符合某种约定。
interface ClockInterface {
currentTime: Date;
}
class Clock implements ClockInterface {
currentTime: Date;
constructor(h: number, m: number) { }
}
九、继承接口
interface Shape {
color: string;
}
interface Square extends Shape {
sideLength: number;
}
let square = <Square>{};
square.color = "blue";
square.sideLength = 10;
一个接口可以继承多个接口。
interface Shape {
color: string;
}
interface PenStroke {
penWidth: number;
}
interface Square extends Shape, PenStroke {
sideLength: number;
}
十、混合类型
一个对象可以同时做为函数和对象使用,并带有额外的属性。
十一、接口继承类
当接口继承了一个类类型时,它会继承类的成员但不包括其实现。
当创建了一个接口继承了一个拥有私有或受保护的成员的类时,这个接口类型只能被这个类或其子类所实现(implement)。
class Control {
private state: any;
}
interface SelectableControl extends Control {
select(): void;
}
class Button extends Control implements SelectableControl {
select() { }
}
class TextBox extends Control {
select() { }
}
// 类“Image”错误实现接口“SelectableControl”。
// 类型 "Image" 中缺少属性 "state",但类型 "SelectableControl" 中需要该属性。ts(2420)
class Image implements SelectableControl {
select() { }
}
这里指的是,接口SelectableControl继承类Control后的接口SelectableControl,类Image在实现时,必须要继承于Control类,也就是必须是它的子类才可以兼容。