TypeScript学习笔记之接口类型

TypeScript的接口,个人理解就是一种约束,包括各种类型的契约或者代码定义上的契约。当然,和java中的用法基本一致,接口可以被继承也可以被实现。

定义一个简单的interface

interface LabelledValue {
  label: string;
}

function printLabel(labelledValue: LabelledValue) {
  console.log(labelledValue.label);
}

let myLabel: LabelledValue = {label: 'this is my label'}
printLabel(myLabel)   // this is my label

注意:
    1、可选属性:label?: string;
    2、只读属性:readonly label: string;(只允许创建的时候修改一次)
    
readonly和const:变量声明用const,属性声明用readonly

看一个readonly的例子:

interface Point {
  readonly x: number;
  readonly y: number;
}

let p1: Point = {x: 121, y: 78}
console.log(p1);    // {x: 121, y: 78}

p1.x = 22   // wrong! 

注意:
    如果是只读型数组,请使用ReadonlyArray

额外属性检查

任意数量属性

interface SquareConfig {
  color?: string;
  width?: number;
  [propName: string]: any;    // 代表任意属性,其中key类型为string,value类型为any任意
}

函数类型接口

接口可以描述js对象中拥有的各种外形。比如如下可以描述js对象具有函数类型:

interface SearchFunc {
  (source: string, subString: string): boolean;
}

let mySearch: SearchFunc;
mySearch = function(src, sub) {     // ts会自动识别参数类型,参数名可以不一致
    let result = src.search(sub);
    return result > -1;
}

其中,source、subString均为string型入参,boolean类型为出参。

可索引的类型

接口描述这种类型,比较有意思,可索引的类型包含两种,一种是对象,一种的数组。可以在接口中描述索引的类型,以及索引值的类型,如下:

interface StringArray {
  [index: number]: string;
}

let z1: StringArray = {1: "awdawd"}
let z2: StringArray = ['admin']
console.log(z1, z2);    // { '1': 'awdawd' } [ 'admin' ]

如上接口,可以被数组实现,也可以被对象实现。索引签名除了number还要string,可以同时使用两种类型的索引。但是要注意:数字类型索引的索引值一定要是字符串索引类型索引值的子类型。举个例子:

class Animal {
  name: string;
}
class Dog extends Animal {
  breed: string;
}

// 错误:使用'string'索引,有时会得到Animal!
interface NotOkay {
  [x: number]: Animal;
  [x: string]: Dog;
}

说明,按照意思是number索引类型是Animal,string索引类型是Dog,Animal必须是Dog的子类型,但是实际恰恰相反——Dog是Animal类型的子类型,所以这里会报错。因为当使用number作索引时,js会将它转换为string,然后再去索引。所以必须保证number索引是string索引的子类型,否则会造成索引值混乱。

使用索引签名实现ReadonlyArray效果:

interface ReadonlyStringArray {
    readonly [index: number]: string;
}
let myArray: ReadonlyStringArray = ["Alice", "Bob"];
myArray[2] = "Mallory"; // error!

实现一个接口

在java里面,接口生来就是被实现的,就好像抽象对象生来就是要被继承一样。

interface ClockInterface {    // 定义接口,包含属性currentTime,所有该接口的实现必须包含该字段
  currentTime: Date;
}

class Clock implements ClockInterface{
  currentTime: Date;    // 该字段必须包含
  constructor(h: number, m: number){};
}

同样地,在接口里面可以再加函数约束,所有实现必须重写该函数:

interface ClockInterface {    // 定义接口,包含属性currentTime,所有该接口的实现必须包含该字段
  currentTime: Date;
  setTime(d: Date);
}

class Clock implements ClockInterface{
  currentTime: Date;    // 该字段必须包含
  setTime(d: Date) {
    this.currentTime = d;
  }
  constructor(h: number, m: number){};
}

继承一个接口

接口和类相似,彼此之间是可以相互继承的,使用关键字extend实现:

interface Shape {
    color: string;
}

interface Square extends Shape {
    sideLength: number;
}

let square = <Square>{};        // 断言,同:{} as Square
square.color = "blue";
square.sideLength = 10;     // { color: 'blue', sideLength: 10 }

这里,Shape接口被Square接口所继承,所以自然Square接口多了一个属性color。

混合类型

有时期望使用接口同时描述对象的属性、方法等,可以如下:

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;

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏ShaoYL

iOS:swift :可选类型

2887
来自专栏互联网杂技

修改数据表(列操作)

前面有介绍数据的增删改查,是针对具体的数据表格里面的数据; 下面是对列的操作; 修改表名 alter table test rename test1; -...

34211
来自专栏hbbliyong

突然顿悟的Javascript中的this

  一直对Javascript中的this都有一种似是而非的感觉,今天突然感觉豁然开朗,特此记录一下。 咱们先看个栗子: <!DOCTYPE html> <ht...

3418
来自专栏向治洪

Koltin数据类之解构申明

所谓的解构声明就是将一个对象解构(destructure)为多个变量,也就是意味着一个解构声明会一次性创建多个变量.简单的来说,一个解构声明有两个动作: 声明了...

20710
来自专栏Albert陈凯

如何对Scala中集合(Collections)进行排序

文章标题: 《如何对Scala中集合(Collections)进行排序》 本文链接: http://www.iteblog.com/archives/1171...

2385
来自专栏恰同学骚年

你必须知道的指针基础-7.void指针与函数指针

  void *表示一个“不知道类型”的指针,也就不知道从这个指针地址开始多少字节为一个数据。和用int表示指针异曲同工,只是更明确是“指针”。

1162
来自专栏青玉伏案

窥探Swift之函数与闭包的应用实例

今天的博客算是比较基础的,还是那句话,基础这东西在什么时候都是最重要的。说到函数,只要是写过程序就肯定知道函数是怎么回事,今天就来讨论一下Swift中的函数的特...

1785
来自专栏前端架构与工程

【译】《Understanding ECMAScript6》- 第二章-函数

函数在任何一门编程语言中都是很重要的一个环节。JavaScript至今已有多年的历史,但是它的函数仍然停留在很初级的阶段。函数问题的大量堆积,以及某些函数非常微...

2007
来自专栏iOS 开发杂谈

iOS 泛型 ObjectType 协变 __covariant 逆变 __contravariant

__covariant(协变):用于泛型数据强转类型,可以向上强转,子类可以转成父类。 __contravariant(逆变):用于泛型数据强转类型,可以向下...

1173
来自专栏Java与Android技术栈

借助Java 8实现柯里化借助Java 8实现柯里化柯里化的好处总结

在函数式编程中,函数的概念跟数学中函数的概念是一样的,类似于“映射”。高阶函数和柯里化是函数式编程的特性。

742

扫码关注云+社区