对象字面量方式(interface)和Class类方式两种定义接口;

1. 接口初探

interface labelValue{
label:string;
}

function printLabel(labelObj:labelValue){
console.log( labelObj.label );
}

let myObj2={ size:10,label:”Size 10 Object” };

2. 可选属性 ?

接口里的属性不全都是必需的。 有些是只在某些条件下存在,或者根本不存在。 可选属性在应用“option bags”模式时很常用,即给函数传入的参数对象中只有部分属性赋值了。
带有可选属性的接口与普通的接口定义差不多,只是在可选属性名字定义的后面加一个?符号。
可选属性的好处之一是可以对可能存在的属性进行预定义,好处之二是可以捕获引用了不存在的属性时的错误

3. 只读属性

3.1 一些对象属性只能在对象刚刚创建的时候修改其值。 你可以在属性名前用 readonly来指定只读属性。
interface Point {
readonly x: number;
readonly y: number;
}
let p1: Point = { x: 10, y: 20 };
p1.x = 5; // error!

3.2 TypeScript具有ReadonlyArray类型,它与Array相似,只是把所有可变方法去掉了,因此可以确保数组创建后再也不能被修改
let a: number[] = [1, 2, 3, 4];
let ro: ReadonlyArray = a;
ro[0] = 12; // error!
ro.push(5); // error!
ro.length = 100; // error!
a = ro; // error! 可以看到就算把整个ReadonlyArray赋值到一个普通数组也是不可以的
可以用类型断言重写:
a = ro as number[];

3.3 readonly VS const
做为变量使用的话用 const,
做为属性则使用readonly。

4. 额外的属性检查

colour是不存在的,ts检测会认为存在bug,

  1. interface SquareConfig {
  2. color?: string;
  3. width?: number;
  4. }
  5. function createSquare(config: SquareConfig): { color: string; area: number } {
  6. // ...
  7. }
  8. let mySquare = createSquare({ colour: "red", width: 100 }); // 检测属性不存在,不通过

解决:1. 类型断言绕开检查
// error: ‘colour’ not expected in type ‘SquareConfig’
let mySquare = createSquare({ colour: “red”, width: 100 });
类型断言:let mySquare = createSqure({width:100, opacity: 0.5} as SquareConfig);

  1. 最佳方式,添加一个字符串索引签名。前提是能够确定这个对象可能具有某些做为特殊用途使用的额外属性。

如果SquareConfig 带有上面定义的类型color和width属性,并且还会带有任意数量的其他属性。

  1. interface SquareConfig {
  2. color?: string;
  3. width?: number;
  4. [propName: string]: any; // 任意签名,不能是前两个
  5. }
  1. 跳过检查的方式,将这个对象赋值给一个另一个变量: 因为 squareOptions不会经过额外属性检查,所以编译器不会报错
    1. let squareOptions = { colour: "red", width: 100 };
    2. let mySquare = createSquare(squareOptions);

    5. 函数类型

    接口不仅可以描述带有属性的对象,也可以描述函数类型。
    5.1 1. 使用接口表示函数类型,需要给接口定义一个调用签名。
    2.格式类似于 只有参数列表和返回值类型的函数定义。
    3.参数列表里的每个参数都需要名字和类型。
    1. // 定义函数接口
    2. interface SearchFunc {
    3. (source: string , subString : string) : boolean;
    4. }
    5. // 使用
    6. let mySearch: SearchFunc;
    7. mySearch = function(source: string, subSstring) { // 参数名不需要与接口里名字匹配也可以
    8. let result = source.search(subString);
    9. return result > -1;
    10. }
    11. // 1. 函数的参数会逐个进行检查,要求对应位置上的参数类型是兼容的。
    12. // 2. 如果不指定类型,TypeScript的类型系统会推断出参数类型,因为函数直接赋值给了SearchFunc类型变量。
    13. // 3. 函数的返回值类型是通过其返回值推断出来的,如果这里函数返回数字或字符串,类型检查器会警告返回值类型与SearchFunc接口中的定义不匹配。

6. 可索引的类型

6.1 与使用接口描述函数类型差不多,我们也可以描述那些能够“通过索引得到”的类型。
6.2 可索引类型具有一个索引签名,它描述了对象索引的类型,还有相应的索引返回值类型。

  1. interface StringArray {
  2. [index: number]: string; // 这个索引签名表示当用number去索引时,会得到string类型的返回值。
  3. }
  4. let myArray: StringArray;
  5. myArray = ["Bob", "Fred"];
  6. let myStr: string = myArray[0];

6.3 TypeScript支持两种索引签名:字符串和数字。
6.4 可以同时使用两种类型的索引,但是数字索引的返回值必须是字符串索引返回值类型的子类型
需要类型保持一致。

  1. interface NumberDictionary {
  2. [index: string]: number;
  3. length: number; // 可以,length是number类型
  4. name: string // 错误,`name`的类型与索引类型返回值的类型不匹配 应该为number,可以设为只读的
  5. }

7. 类类型

7.1 接口实现

与C#或Java里接口的基本作用一样,TypeScript也能够用它来明确的强制一个类去符合某种契约

1.extends : 创建一个类的子类,继承某个类,可以使用父类的方法,也可以重写父亲方法;
只要那个类不是声明为**final或者那个类定义为abstract**的就能继承;
2.implements : 是实现多个接口,接口的方法一般为空的,必须重写才能使用。
class A extends B implements C,D,E

  1. interface ClockInterface { // 公共部分
  2. currentTime: Date;
  3. setTime(d: Date);// 描述方法,类里实现
  4. }
  5. // 接口描述了类的公共部分,而不是公共和私有两部分;
  6. // 它不会检查类是否具有某些私有成员。
  7. class Clock implements ClockInterface {
  8. currentTime: Date;
  9. setTime(d: Date) {
  10. this.currentTime = d;
  11. }
  12. constructor(h: number, m: number) { }
  13. }

7.2 类的静态部分和实例部分的区别

1.类具有两个类型:静态部分的类型和实例部分的类型
2.用构造器(constructor)去定义一个接口并试图定义一个类去实现这个接口时会报错,
3.原因是: 类实现一个接口时,只对实例部分进行类型检查,constructor存在于类的静态部分,不检查。

  1. interface ClockConstructor {
  2. new (hour: number, minute: number);
  3. }
  4. class Clock implements ClockConstructor {
  5. currentTime: Date;
  6. constructor(h: number, m: number) { }
  7. }
  8. // 解决
  9. // 直接操作类的静态部分

7.3 继承接口

  1. 和类一样,接口可以相互继承;
  2. 可以从一个接口复制成员到另一个接口,更灵活的将接口分割到可重用的模板里;
  3. 一个接口继承多个接口。 ```typescript interface Shape { color: string; } interface Square extends Shape { // 继承接口Shape sideLength: number; }

let square = {}; // let squre = {}; 类似强制类型转换,<类型>值 或者 值 as 类型,接口不存在的类型不可以断言 square.color = ‘red’; square.sideLength = 10; //////////////////////////////// //继承多个接口 interface Shape { color: string; } interface PenStroke { penWidth: number; }

interface Square extends Shape, PenStroke { // Angular一样 sideLength: number; } let square = {}; square.color = “blue”; square.sideLength = 10; square.penWidth = 5.0;

  1. <a name="0czqe"></a>
  2. #### 7.4 混合类型(使用第三方库需要这样完整定义)
  3. 1. 一个对象多个类型。
  4. ```typescript
  5. interface Counter {
  6. (start: number): string; // 函数类型
  7. interval: number; // 数字类型
  8. reset(): void; // 实例方法
  9. }
  10. function getCounter(): Counter {
  11. let counter = <Counter>function (start: number) { };
  12. counter.interval = 123;
  13. counter.reset = function () { };
  14. return counter;
  15. }
  16. let c = getCounter();
  17. c(10);
  18. c.reset();
  19. c.interval = 5.0;

7.5 接口继承类

  1. 接口继承一个类类型时,会继承类的成员但不包括实现;
  2. 接口同样会继承到类的peivate和proteced成员。所以这个接口类型只能被这个类或其子类所实现。 ```typescript class Control { // 父类,有private所以是私有的 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 {

} ```