TypeScript中文手册
3,接口
### 3.1 接口初探 - 我们传入的对象参数实际上会包含很多属性,但是编译器只会检查那些必需的属性是否存在,并且其类型是否匹配。 - 类型检查器不会去检查属性的顺序,只要相应的属性存在并且类型也是对的就可以 ```typescript interface LabelledValue { label: string; } function printLabel(labelledObj: LabelledValue) { console.log(labelledObj.label); } let myObj = {size: 10, label: "Size 10 Object"}; printLabel(myObj); ``` ### 3.2 可选属性 > 带有可选属性的接口与普通的接口定义差不多,只是在可选属性名字定义的后面加一个`?`符号 ```typescript interface SquareConfig { color?: string; width?: number; } ``` ### 3.3 只读属性 > 一些对象属性只能在对象刚刚创建的时候修改其值。 你可以在属性名前用`readonly`来指定只读属性 ```typescript interface Point { readonly x: number; readonly y: number; } let p1: Point = { x: 10, y: 20 }; //只能在创建时赋值 p1.x = 5; // 再次赋值报错 error! ``` - TypeScript具有`ReadonlyArray<T>`类型,与`Array<T>`相似,只是把所有可变方法去掉,可以确保数组创建后再也不能被修改: ```typescript let a: number[] = [1, 2, 3, 4]; let ro: ReadonlyArray<number> = a; ro[0] = 12; // error! ro.push(5); // error! ro.length = 100; // error! a = ro; // error! ``` ### 3.4 额外的属性检查 - 接口使用可选属性可能导致bug ```typescript interface SquareConfig { color?: string; width?: number; } function createSquare(config: SquareConfig): { color: string; area: number } { // ... } //一个对象字面量存在任何“目标类型”不包含的属性时,你会得到一个错误 // error: 'colour' not expected in type 'SquareConfig' let mySquare = createSquare({ colourrrrrrr: "red", width: 100 }); ``` - 绕开这些检查非常简单。 最简便的方法是使用类型断言: ```typescript let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig); ``` - 最佳的方式是能够添加一个字符串索引签名 ```typescript interface SquareConfig { color?: string; width?: number; //表示的是SquareConfig可以有任意数量的属性,并且只要它们不是color和width,那么就无所谓它们的类型是什么 [propName: string]: any; } ``` - 最后一种方式就是将这个对象赋值给一个另一个变量: 因为`squareOptions`不会经过额外属性检查,所以编译器不会报错 ```typescript let squareOptions = { colour: "red", width: 100 }; let mySquare = createSquare(squareOptions); ``` ### 3.5 函数类型 - 为了使用接口表示函数类型,我们需要给接口定义一个调用签名 ```typescript interface SearchFunc { //参数列表里的每个参数都需要名字和类型 (source: string, subString: string): boolean; } ``` - 定义后,我们可以像使用其它接口一样使用这个函数类型的接口 ```typescript //创建一个函数类型的变量,并将一个同类型的函数赋值给这个变量 let mySearch: SearchFunc; mySearch = function(source: string, subString: string) { let result = source.search(subString); return result > -1; } //对于函数类型的类型检查来说,函数的参数名不需要与接口里定义的名字相匹配 mySearch = function(src: string, sub: string): boolean { let result = src.search(sub); return result > -1; } //函数的参数会逐个进行检查,要求对应位置上的参数类型是兼容的。 如果你不想指定类型,TypeScript的类型系统会推断出参数类型, mySearch = function(src, sub) { let result = src.search(sub); return result > -1; } ``` ### 3.6 可索引的类型 - 索引签名 - 数字索引签名 ```typescript interface StringArray { [index: number]: string; } let myArray: StringArray; myArray = ["Bob", "Fred"]; let myStr: string = myArray[0]; ``` - 字符串索引签名 ```typescript interface NumberDictionary { [index: string]: number; length: number; // 可以,length是number类型 name: string // 错误,`name`的类型与索引类型返回值的类型不匹配 } ``` - 将索引签名设置为只读,这样就防止了给索引赋值: ```typescript interface ReadonlyStringArray { readonly [index: number]: string; } let myArray: ReadonlyStringArray = ["Alice", "Bob"]; myArray[2] = "Mallory"; // error! ``` ### 3.7 类类型 ##### 3.7.1 实现接口 > 与C#或Java里接口的基本作用一样,TypeScript也能够用它来明确的强制一个类去符合某种契约 > > 接口描述了类的公共部分,而不是公共和私有两部分。 它不会帮你检查类是否具有某些私有成员。 ```typescript interface ClockInterface { currentTime: Date; setTime(d: Date); //在接口中描述一个方法 } class Clock implements ClockInterface { currentTime: Date; setTime(d: Date) { //在类里实现接口方法 this.currentTime = d; } constructor(h: number, m: number) { } } ``` ##### 3.7.2 类静态部分与实例部分的区别 - 当你用构造器签名去定义一个接口并试图定义一个类去实现这个接口时会得到一个错误,因为当一个类实现了一个接口时,只对其实例部分进行类型检查。 constructor存在于类的静态部分,所以不在检查的范围内。因此,我们应该直接操作类的静态部分。 ```typescript interface ClockConstructor { new (hour: number, minute: number); } class Clock implements ClockConstructor { currentTime: Date; constructor(h: number, m: number) { } //error } ``` ### 3.8 继承接口 - 和类一样,接口也可以相互继承。 这让我们能够从一个接口里复制成员到另一个接口里 ```typescript interface Shape { color: string; } interface Square extends Shape { sideLength: number; } ``` - 一个接口可以继承多个接口,创建出多个接口的合成接口 ```typescript interface Shape { color: string; } interface PenStroke { penWidth: number; } interface Square extends Shape, PenStroke { sideLength: number; } ``` ### 3.9 混合类型 - 一个对象可以同时做为函数和对象使用,并带有额外的属性 ```typescript 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; ``` ### 3.10 接口继承类 - 当接口继承了一个类类型时,它会继承类的成员但不包括其实现。 - 接口同样会继承到类的private和protected成员。 ```typescript class Control { private state: any; } interface SelectableControl extends Control { select(): void; } class Button extends Control implements SelectableControl { select() { } } ```
顶部
收展
底部
[TOC]
目录
1,基础类型
2,变量声明
3,接口
4,类
5,函数
6,泛型
7,枚举
8,类型推论
9,类型兼容性
10,高级类型
11,符号Symbols
12,Iterators(迭代)
13,模块
14,命名空间
15,模块解析