typescript接口
typescript的核心原则之一就是对值所具有的结构进行类型检查。被称作,‘鸭式变型法’或“结构性子类型化”
接口初探
function fun(first: { label: string }, second: {value:number},third:number,fourth?:number) {}fun({ label: '1' }, {value : 1},1)js=>function fun(first, second, third, fourth) {}fun({ label: '1' }, { value: 1 }, 1);
可选类型
interface SquareConfig{color?:string;width?:number;}
两个好处。1.可以对可能存在的属性进行预定义。2.可以捕获引用不存在的属性时的错误。
只读属性
interface Point{readonly x : number;readonly y : number;}
let a : number[]=[1,2,3,4];let ro: ReadonlyArray<number>=a;ro[1]=1 //error!ro.push(1) //errora=po//error
typescript具有ReadonlyArray类型,与Array相似,去掉了所有的可变方法,可以确保数组创建后不被更改。把ReadonlyArray复制到普通数组需要借助于类型断言
a = po as number[];
readonly VS const
作为变量用const,属性用readonly
额外的属性检查
错误的使用
interface SquareConfig {color?: string;width?: number;}function createSquare(config: SquareConfig): { color: string; area: number } {// ...}let mySquare = createSquare({ colour: "red", width: 100 });
解决方法:
1.断言 let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig);
2.字符串索引签名
interface SquareConfig {color?: string;width?: number;[propName: string]: any;}
注意:不应该去绕开这些检查,应该去修改接口定义
函数类型
描述函数类型
interface SearchFunc {(source: string, subString: string): boolean;}let mySearch: SearchFunc;mySearch = function(source: string, subString: string) {let result = source.search(subString);return result > -1;}// 函数类型的类型检查来说,函数的参数名不需要与接口里定义的名字相匹配。let mySearch: SearchFunc;mySearch = function(src: string, sub: string): boolean {let result = src.search(sub);return result > -1;}// 如果你不想指定类型,TypeScript的类型系统会推断出参数类型,因为函数直接赋值给了 SearchFunc类型变let mySearch: SearchFunc;mySearch = function(src, sub) {let result = src.search(sub);return result > -1;}
可索引的类型
与使用接口描述函数类型差不多,也可以使用接口描述能够“通过索引得到的类型”,比如ageMap[“detail”]。
interface StringArray{[index:number]:string;}let myArray:StringArray;myArray=["Bob]let myStr:string =myArray[0]
定义了StringArray接口,具有索引标签,索引签名表示了当用number去索引StringArray时会得到string类型的返回值。
TypeScript支持两种索引签名:字符串和数字。可以同时使用两种类型的索引,数字索引返回值必须是字符串索引返回值的子类型。因为使用number来索引时,JavaScript会将它转换成string然后再去索引对象。所以需要保持一致。
class Animal {name: string;}class Dog extends Animal {breed: string;}// 错误:使用数值型的字符串索引,有时会得到完全不同的Animal!interface NotOkay {[x: number]: Animal;[x: string]: Dog;}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!
类类型
实现接口
作用与Java类似
interface ClockInterface {currentTime: Date;setTime(d: Date);}class Clock implements ClockInterface {currentTime: Date;setTime(d: Date) {this.currentTime = d;}constructor(h: number, m: number) { }}
接口描述了公共部分,不会检验类是否具有某些私有成员。
类静态部分与实例部分的区别。
当一个类实现了一个接口时,只对其实例部分进行类型检查
#
继承接口
和类一样,接口可以相互继承,能够从一个接口里复制成员到另一个接口里,可以灵活地将接口分割到可重用的模块里。
// 可以继承多个接口interface Shape {color: string;}interface PenStroke {penWidth: number;}interface Square extends Shape, PenStroke {sideLength: number;}let square = <Square>{};square.color = "blue";square.sideLength = 10;square.penWidth = 5.0;
混合类型
由于JavaScript的动态灵活特点,希望一个对象可以同时具有多种类型
interface Counter {(start: number): string;interval: number;reset(): void;}function getCounter(): Counter {let counter = <Counter>function (start: number) { };counter.interval = 123;counter.reset = function () { };return counter;}let c = getCounter();c(10);c.reset();c.interval = 5.0;
接口继承类
当接口继承了一个类时,会继承类的成员但不包括类的实现。接口会继承到类的private和protected成员。例如当接口继承了含有私有或保护成员的类时,这个接口的类型只能被这个类或其子类所实现。
class Control {private state: any;}interface SelectableControl extends Control {select(): void;}class Button extends Control implements SelectableControl {select() { }}class TextBox extends Control {select() { }}// 错误:“Image”类型缺少“state”属性。class Image implements SelectableControl {select() { }}class Location {}
