接口
description:对值所具有的结构进行类型检查
注意:传入的对象参数实际上会包含很多属性,但是编译器只会检查那些必需的属性是否存在,并且检查其类型是否匹配(话虽如此,但是引用没有被检查的属性时还是会报错hhhhh,所以最好要做到一一对应)
// 注意:
interface LabelValue {
label: string
}
function print(labelObj: LabelValue){
console.log(labelObj)
}
-
只读属性(readonly)
interface Point{ readonly x: number; readonly y: number; } // 数组的只读(ReadyonlyArray) let arr: ReadyonlyArray<number> = [1,2,3] arr[0] = 12; // error! arr.push(5); // error! arr.length = 100; // error! let a = arr; // error! 可以看到就算把整个ReadonlyArray赋值到一个普通数组也是不可以的 可以用断言重写 a = arr as number[];
-
可选属性(?😃
可选属性只意味着接口实例里可以没有这个的属性,并不意味着可以多出其他的属性(有时候不会触发额外的检查,下面会讲到) -
额外的检查
interface SquareConfig { color?: string; width?: string; } function createSquare(config: SquareConfig) { // ... } // 以字面量形式传入,会触发额外的检查(检查是否有不在接口定义中的属性) let mySquare = createSquare({ colour: "red", width: 100 }); // 以变量形式传入,不会触发额外的检查 let obj = { colour: "red", width: 100 } let mySquare = createSquare(obj); // 怎么绕开这个额外的检查呢? // 方法一: 以变量形式传入(如上) // 方法二: 断言 let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig); // 方法三:添加一个字符串索引签名(前提是你能够确定这个对象可能具有某些做为特殊用途使用的额外属性) interface SquareConfig { color?: string; width?: number; [propName: string]: any; // 接口定义为此形式(表示的是SquareConfig可以有任意数量的属性,并且只要它们不是color和width,那么就无所谓它们的类型是什么) // ps:索引签名的名称(如:{ [index: string]: { message: string } } 里的 index )除了可读性外,并没有任何意义 }
-
接口表示函数类型(就像是一个只有参数列表和返回值类型的函数定义)
interface SearchFunc { (source: string, subString: string): boolean } let fn: SearchFunc; fn = (source:string) => { } // 注意:这里只传一个参数是可以的,但只能是string类型(与接口对应) 并且,函数的参数名不需要与接口里定义的名字相匹配(source也可以写成s...)
-
可索引类型
- 可索引类型具有一个索引签名,它描述了对象索引的类型,还有相应的索引返回值类型
- ts支持两种索引签名:字符串和数字,但是数字索引的返回值必须是字符串索引返回值类型的子类型(因为当使用 number来索引时,JavaScript会将它转换成string然后再去索引对象。 也就是说用 100(一个number)去索引等同于使用"100"(一个string)去索引,因此两者需要保持一致)
class Animal { name: string; } class Dog extends Animal { breed: string; } // 错误:使用数值型的字符串索引,有时会得到完全不同的Animal! interface NotOkay { [x: number]: Animal; // Animal不是Dog的子类型(error) [x: string]: Dog; }
- 字符串索引签名能够很好的描述dictionary模式,并且它们也会确保所有属性与其返回值类型相匹配
interface NumberDictionary { [index: string]: number; length: number; // 可以,length是number类型 name: string // 错误,`name`的类型与索引类型返回值的类型不匹配 }
- 可以将索引签名设置为只读,这样就防止了给索引赋值
interface ReadonlyStringArray { readonly [index: number]: string; } let myArray: ReadonlyStringArray = ["Alice", "Bob"]; myArray[2] = "Mallory"; // error!
-
类类型
interface ClockInterface { currentTime: Date; setTime(d: Date): void; } // 构造器签名(检查构造函数类型) interface ClockConstructor { new (hour: number, minute: number); } // ts检查类型 class Clock implements ClockInterface { currentTime = new Date(); setTime(d: Date){} constructor(h: number, m: number){ // 接口描述了类的公共部分,而不是公共和私有两部分。 它不会帮你检查类是否具有某些私有成员。 } }
-
接口继承类
当接口继承了一个类类型时,它会继承类的成员但不包括其实现。 就好像接口声明了所有类中存在的成员,但并没有提供具体实现一样。 接口同样会继承到类的private和protected成员。 这意味着当你创建了一个接口继承了一个拥有私有或受保护的成员的类时,这个接口类型只能被这个类或其子类所实现