在传统的面向对象语言中,接口(Interface)好比协议,它会列出一系列的规则(即对行为进行抽象),再由类来实现这些规则。而TypeScript中的接口更加灵活,除了包含常规的作用之外,它还能扩展其它的类、为对象的类型命名以及约束值的结构等,大大消除了许多潜在的错误。

一、属性

  TypeScript中的接口可通过声明属性和其类型来限制对象的结构。例如定义一个名为Person的接口,包含一个字符串类型的name属性和一个数字类型的age属性,如下所示。

interface Person {
name: string;
age: number;
}

  当声明一个Person类型的对象时,必须将两个属性都定义,并且类型也要与接口中的一致,如下所示。

let worker: Person = {
name: "strick",
age:
};

  一旦在worker对象中少定义某个接口中的属性或多一个在接口中未声明的属性,那么就会在编译阶段报错。注意,TypeScript的类型检查器不会比对属性在接口和对象中的定义顺序,只要名称和类型匹配,就能编译通过。

1)可选属性

  TypeScript允许接口中的属性定义为可选的,只要在属性名后跟问号(?),就能变为可选属性,如下所示。

interface Person {
school?: string;
}

  可选属性既能预定义可能需要的属性,也能在捕获没有的属性时给出带有启发作用的错误提示,例如在创建worker对象时,定义一个schools属性(如下所示),在编译时就会报"'schools' does not exist in type 'Person'. Did you mean to write 'school'?"的错误。

let worker: Person = {
schools: "university"
};

  由此可知,在对象中定义一个未在接口中声明的属性仍然是不允许的。

2)只读属性

  如果要让对象的某个属性只能在创建时被赋值,那么可以将readonly关键字作用于相应的接口属性,使其变为只读的,如下所示。

interface Person {
readonly gender: string;
}

  由于gender是一个只读属性,因此不能在对象初始化后对其进行修改,如下所示。

let worker: Person = {    //正确
gender: "男"
};
worker.gender = "女"; //错误

3)任意属性

  当接口需要包含任意属性时,可以通过索引的方式实现,如下所示,用方括号将索引名和索引类型包裹起来。

interface Person {
[prop: string]: string;
}

  在使用Person类型时,可以传任意多个字符串类型的属性,如下所示。

let worker: Person = {
name: "strick",
gender: "男"
};

  注意,一旦声明了任意属性之后,那么必选属性和可选属性都得是其类型的子类型。在下面的示例中,由于可选的age属性的类型是number,不是string的子类型,因此在编译时会报错。

interface Person {
name: string; //正确
age?: number; //错误
[prop: string]: string;
}

  TypeScript除了支持字符串类型的索引之外,还支持数字类型的索引,如下所示。

interface Person {
[prop: number]: number;
}

  有一点需要注意,当在接口中同时定义字符串和数字两种类型的索引时,后者对应的值类型得是前者的子类型。因为这个原因,导致下面的代码无法在编译时通过。

interface Person {
[prop: string]: string;
[prop: number]: number; //错误
}

  TypeScript之所以如此限制,是因为JavaScript会将数字自动转换成字符串后再去索引对象,例如用10和“10”两个值去索引,得到的结果是一样的,所以两种索引对应的值类型要保持一致。

二、继承

1)类继承接口

  与C#、Java等面向对象语言一样,TypeScript中的类也能继承接口,并且接口中的成员会让类强制实现。有了接口之后,它的任何更改都有可能导致编译错误,从而就能保证相关代码的同步。下面通过一个示例来演示类继承接口,首先创建一个名为Person的接口,包含name属性和getName()方法,如下所示。

interface Person {
name: string;
getName(): string;
}

  然后再创建一个名为Member的类,通过implements关键字继承Person接口,如下所示。在编译时,一旦发现类中缺少接口的属性或方法,就会马上报错。

class Member implements Person {
name: string = "strick";
getName() {
return this.name;
}
}

  类能继承多个接口,只要在类中实现它的成员,就能编译成功,如下所示,Member类继承了Person和Profile两个接口,限于篇幅原因,在其内部省略了name和getName()两个成员的实现。

interface Profile {
school: string;
}
class Member implements Person, Profile {
school: string = "university";
}

  注意,类不能实现接口中的所有成员,例如在接口中定义一个构造器,再用一个类通过构造函数来实现这个接口,此时编译将会失败,代码如下所示。

interface Person {
new (name: string);
}
class Member implements Person {
constructor(name: string) { }
}

  类包含静态和实例两部分,由于编译器只会对接口的实例部分进行类型检查,而constructor()函数属于类的静态部分,因此会被忽略,从而导致无法在类中找到匹配的成员来实现接口。

  如果要实现接口中的构造器,那么有两种方式可供选择。第一种是参数回调,如下代码所示,Member类不再直接继承Person接口,而是作为参数传递给createPerson()函数,并且其第一个参数被声明为Person类型。

class Member {
constructor(name: string) { }
}
function createPerson(ctor: Person, name: string) {
return new ctor(name);
}
createPerson(Member, "strick");

  第二种是类表达式,如下代码所示,将Man变量声明为Person类型,并把Member类赋给它。

let Man: Person = class Member {
constructor(name: string) { }
}

2)接口继承接口

  接口之间也可相互继承,这样既能更细粒度的分割接口,也能最大化的重用代码。与类不同的是,只需将其它的接口成员复制过来,而不必实现它们。在下面的示例中,Square接口通过extends关键字继承了Shape接口。

interface Shape {
background: string;
}
interface Square extends Shape {
width: number;
}

  一个接口还可以继承多个其它接口,创建出一个合成接口,如下所示,extends后面跟了Shape和Border两个接口。

interface Border {
color: string;
}
interface Ellipse extends Shape, Border {
angle: string;
}

3)接口继承类

  当接口继承一个类时,它会继承类的所有成员(包括私有和受保护的成员),但不会去实现它们。以下面的TextBox接口为例,它继承了Control类。

class Control {
private width: number;
protected height: number;
}
interface TextBox extends Control {
type: string;
}
class Tel implements TextBox {
type: string = "tel";
}

  上例中的Tel类直接继承了TextBox接口,虽然实现了接口中的type属性,但仍然会报“Type 'Tel' is missing the following properties from type 'TextBox': width, height”的错误。因为Button接口继承的width和height两个属性也需要实现。为了避免出现这些错误,可以通过Control的子类来实现TextBox接口,如下所示。

class Password extends Control implements TextBox {
type: string = "password";
}

TypeScript躬行记(2)——接口的更多相关文章

  1. TypeScript躬行记(3)——类

    类是对对象的抽象,描述了对象的特征和行为,而对象就是类的实例.ES6引入了类的概念(相关内容可参考ES类和ES6类的继承两节),TypeScript在此基础上,不仅根据ES7等规范完善了类的语法,还添 ...

  2. TypeScript躬行记(5)——类型兼容性

    TypeScript是一种基于结构类型的语言,可根据其成员来描述类型.以结构相同的Person接口和Programmer类为例,如下所示. interface Person { name: strin ...

  3. TypeScript躬行记(7)——命名空间

    TypeScript中的命名空间可将那些具有内在联系的接口.类或对象等代码组织在一起,既能隔离作用域,也能避免命名冲突,并且使得代码结构清晰,更易追踪.在命名空间内部,所有实体部分默认都是私有的,需要 ...

  4. TypeScript躬行记(8)——装饰器

    装饰器(Decorator)可声明在类及其成员(例如属性.方法等)之上,为它们提供一种标注,用于分离复杂逻辑或附加额外逻辑,其语法形式为@expression.expression是一个会在运行时被调 ...

  5. TypeScript躬行记(6)——高级类型

    本节将对TypeScript中类型的高级特性做详细讲解,包括交叉类型.类型别名.类型保护等. 一.交叉类型 交叉类型(Intersection Type)是将多个类型通过“&”符号合并成一个新 ...

  6. TypeScript躬行记(4)——泛型

    泛型是程序设计语言中的一种风格或范式,相当于类型模板,允许在声明类.接口或函数等成员时忽略类型,而在未来使用时再指定类型,其主要目的是为它们提供有意义的约束,提升代码的可重用性. 一.泛型参数 当一个 ...

  7. TypeScript躬行记(1)——数据类型

    TypeScript不仅支持JavaScript所包含的数据类型,还额外扩展了许多实用的数据类型,例如枚举.空值.任意值等. 一.JavaScript的数据类型 JavaScript的数据类型包括6种 ...

  8. ES6躬行记 笔记

    ES6躬行记(18)--迭代器 要实现以下接口## next() ,return,throw 可以用for-of保证迭代对象的正确性 例如 var str = "向

  9. ES6躬行记(1)——let和const

    古语云:“纸上得来终觉浅,绝知此事要躬行”.的确,不管看了多少本书,如果自己不实践,那么就很难领会其中的精髓.自己研读过许多ES6相关的书籍和资料,平时工作中也会用到,但在用到时经常需要上搜索引擎中查 ...

随机推荐

  1. Oracle instant client免安装Oracle客户端配置

    不想安装几个G的完整版client,可以直接通过安装包安装的时候选择instant client,如果没有安装包,也可以直接去官网下载一个即时客户端,64位的windows包大小只有78MB左右 传送 ...

  2. js 把数组中每个元素的某个字段取出

    方法一:map() let cities = [ {city:"北京",bOn:false}, {city:"上海",bOn:false}, {city:&qu ...

  3. Serlvet之cookie和session学习

    HTTP 协议 Web通信需要一种语言,就像中国人讲中文,欧美说英文,Web使用的HTTP协议,也叫超文本协议. 使用HTTP协议的人分为两类:客户端和服务端.请求资源的角色是客户端,提供资源的是服务 ...

  4. 结合RBAC模型讲解权限管理系统需求及表结构创建

    在本号之前的文章中,已经为大家介绍了很多关于Spring Security的使用方法,也介绍了RBAC的基于角色权限控制模型.但是很多朋友虽然已经理解了RBAC控制模型,但是仍有很多的问题阻碍他们进一 ...

  5. 20191107-5 beta week 2/2 Scrum立会报告+燃尽图 04

    此作业的要求参见https://edu.cnblogs.com/campus/nenu/2019fall/homework/9957 一.小组情况 队名:扛把子 组长:孙晓宇 组员:宋晓丽 梁梦瑶 韩 ...

  6. Python文件和数据格式化(教程)

    文件是一个存储在副主存储器的数据序列,可包含任何数据内容. 概念上,文件是数据的集合和抽象,类似的,函数是程序的集合和抽象. 用文件形式组织和表达数据更有效也更加灵活. 文件包括两种形式,文本文件和二 ...

  7. 【开发工具 - Android Studio】之AndroidStudio使用笔记

    一.关闭自动更新: 问题:刚刚安装Android Studio的童鞋可能会遇到这样一个问题:Android Studio在打开的时候一直在下载一些东西,浪费很多时间,而且最终大多都会显示下载失败等等, ...

  8. java 抽象类和接口整理

    java中定义一些不含方法体的方法,方法体的实现交给该类的子类根据自己的具体情况去实现,这样的方法就是abstract修饰的抽象方法,包含抽象方法的类叫抽象类,用abstract修饰 抽象方法: ab ...

  9. Apache用户认证、域名跳转、Apache访问日志

    5月29日任务 课程内容: 11.18 Apache用户认证11.19/11.20 域名跳转11.21 Apache访问日志扩展 apache虚拟主机开启php的短标签 http://ask.apel ...

  10. 腾讯面试官问我Java中boolean类型占用多少个字节?我说一个,面试官让我回家等通知

    本文首发于微信公众号:程序员乔戈里 什么是boolean类型,根据官方文档的描述: boolean: The boolean data type has only two possible value ...