接口

在JavaScript中没有这个概念。

接口初探

function printLabel(labelledObj: { label: string }) {  console.log(labelledObj.label);}// label为传入对象参数必有的一个属性let myObj = { size: 10, label: "Size 10 Object" };printLabel(myObj);

下面利用接口重写例子

//个人理解为将传入参数要求提出来,看起来更加清晰interface LabelledValue {  label: string;}function printLabel(labelledObj: LabelledValue) {  console.log(labelledObj.label)}let myObj = { size: 10, label: "Size 10 Object" };printLabel(myObj);

还有一点值得提的是,类型检查器不会去检查属性的顺序,只要相应的属性存在并且类型也是对的就可以。

可选属性

接口里的属性不全都是必需的。

interface SquareConfig {  color?:string; //注意这里是分号哟  width?:number;}function createSquare(config:SquareConfig):{color:string;area:number}{  let newSquare = {color: "white", area: 100};  if (config.color) {    newSquare.color = config.color;  }  if (config.width) {    newSquare.area = config.width * config.width;  }  return newSquare;}let mySquare = createSquare({color: "black"});

只读属性

只读属性创建后不能再次修改。

interface Point {    readonly x: number;    readonly y: number;}let p1: Point = { x: 10, y: 20 };p1.x = 5; // error!

下面的代码可以让ro数组创建后再也无法改变

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!a = ro as number[]; //right

readonly VS const
官方解说:最简单判断该用readonly还是const的方法是看要把它做为变量使用还是做为一个属性。 做为变量使用的话用 const,若做为属性则使用readonly

额外的属性检查

可以漏写部分属性,但不能多写属性或者错写属性,即如果传入的对象中含有目标类型不存在的属性,TS 额外的属性检查机制会进行报错。
官方提供了绕开 TS 的额外属性检查的办法:

// 1. 使用类型断言let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig);// 2. 声明接口时来一个任意类型,此时这个声明为该接口的对象,可以有任意数量、任意类型、只要名字不是 color 或 width 的属性interface SquareConfig {  color?: string;  width?: number;  [propName: string]: any;}// 3. 更简单,只要把对象赋值到另一个变量上(抽离出来)即可:let squareOptions = { colour: "red", width: 100 };let mySquare = createSquare(squareOptions);

个人感觉不要使用,毕竟这个是TS来帮我们检查BUG的。

函数类型

使用接口表示函数类型

//像是一个只有参数列表和返回值类型的函数定义。参数列表里的每个参数都需要名字和类型。interface SearchFunc {  (source:string, subString:string):boolean}

使用方法

let mySearch:SearchFunc = function(src:string,sub:string){  let result = source.search(sub)  return result > -1}

当然可以省略部分代码

let mySearch:SearchFunc = function(src,sub){  let result = source.search(sub)  return result > -1}

可索引类型

interface StringArray {  [index: number]: string;}let myArray: StringArray;myArray = ["Bob", "Fred"];let myStr: string = myArray[0];

这个索引签名表示了当用 number去索引StringArray时会得到string类型的返回值。

class Animal {  name: string;}class Dog extends Animal {  breed: string;}interface NotOkay {  [x: number]: Animal;//此处错误  [x: string]: Dog;}

因为当使用 number来索引时,JavaScript会将它转换成string然后再去索引对象。 也就是说用 100(一个number)去索引等同于使用"100"(一个string)去索引。
记住一句话:数字类型索引的返回值必须是字符串类型索引返回值的子类型。这里AnimalDog的父类型,所以错误。

此外,字符串索引签名能够很好的描述dictionary模式,并且它们也会确保所有属性与其返回值类型相匹配。
如:

interface NumberDictionary {  [index: string]: number;  length: number;    // 可以,length是number类型  name: string       // 错误,`name`的类型与索引类型返回值的类型不匹配}//这里一知半解不太明白是什么意思

最后你还可以给索引签名设置为只读,防止了给索引赋值:

interface ReadonlyStringArray {    readonly [index: number]: string;}

类类型

这一部分等看了TS中的类以后再回头来看

继承接口

interface Shape {  color: string;}interface Square extends Shape {  sideLength: number;}let square = <Square>{};square.color = "blue";square.sideLength = 10;

这样square的2个参数都要受限制了
一个接口可以继承多个接口,创建出多个接口的合成接口。

interface Shape {  color: string;}interface PenStroke {  penWidth: number;}interface Square extends Shape, PenStroke {  sideLength: number;}

混合类型

这个也留着以后回头来看

接口继承类

同上