TypeScript Interface(接口)

类型检查专注于解析值所具有的"形态",这是TypeScript的核心原则之一。这个有时候被称为"duck typing"或者"structural subtyping"。在TypeScript中,Interface中写入这些类型的命名规范,并且也是一种强有力的方式来对你的代码或者项目的外部代码进行约束。

我们来实现第一个接口
要看看interface怎么工作的最简单的方式就是我们来写一个例子:

function printLabel(labelledObj: {label: string}) {
  console.log(labelledObj.label);
}
var myObj = {size: 10, label: "Size 10 Object"};
printLabel(myObj);

类型检查器将会检查调用的"printLabel"。printLabel函数需要有一个对象作为参数,并且这个对象有"label"属性,该属性值类型是string。注意,我们的对象其实有比这个更多的属性,但编译器只检查当前匹配和需要的属性的类型。
我们再写一次上面的例子,只是这次我们使用interface来描述所需的"label"属性值是一个字符串:

interface LabelledValue {
  label: string;
}
function printLabel(labelledObj: LabelledValue) {
  console.log(labelledObj.label);
}
var myObj = {size: 10, label: "Size 10 Object"};
printLabel(myObj);

"LabelledValue"是一个名称,我们用它来描述前面那个例子中的需求。它依然体现出需要一个字符串类型的并且名为"label"的属性。注意,我们没有明确的说明在其他语言中也是在"printLabel"函数传入对象以实现此接口。这里,我们也仅仅是提下这个问题。如果我们传递给函数的对象符合要求,那么它就被允许了。
值的指出的是,类型检查不需求这些属性是来自挑选或者排序之后的,只需要interface所需的属性是存在的,并且类型也是相对应的即可。

属性可选
在interface中,并不是所有的属性都是必需的。有些可能是在某个条件下才需要,不是一直需要用到。当用户将一个对象传入到一个只具有一对属性的函数时(如创建一个"option bags"的方式),这些可选属性是很方便的。
这里有个这种方式的例子:

interface SquareConfig {
  color?: string;
  width?: number;
}
function createSquare(config: SquareConfig): {color: string; area: number} {
  var newSquare = {color: "white", area: 100};
  if (config.color) {
    newSquare.color = config.color;
  }
  if (config.width) {
    newSquare.area = config.width * config.width;
  }
  return newSquare;
}
var mySquare = createSquare({color: "black"});

可选属性的interface和写普通的interface相似,只是每个可选属性用"?"符号标识,以作为申明这是可选的。
可选属性的有点是,你可以描述这些可能会用到的属性,同时还可以捕捉你明确了的那些不期望使用的属性。举例说明,我们为传入的"createSquare"输入了一个错误的属性名称,我们需要抛出一个错误信息来通知我们。

interface SquareConfig {
  color?: string;
  width?: number;
}
function createSquare(config: SquareConfig): {color: string; area: number} {
  var newSquare = {color: "white", area: 100};
  if (config.color) {
    newSquare.color = config.collor;  // 类型检测器将会捕捉到你传入了错误的名称
  }
  if (config.width) {
    newSquare.area = config.width * config.width;
  }
  return newSquare;
}
var mySquare = createSquare({color: "black"});

函数类型

interface能够做和javascript的对象一样的事:描述形态的范围。除了描述一个对象的属性外,interface还可以描述函数类型。
用interface描述一个函数的类型,我们需要给interface一个调用标识。这就像一个只有参数列表和返回值类型的函数声明。

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

一旦定义后,我们就能和其他interface一样使用它了。在这里,我们将展示如何创建一个函数类型的变量并且将其赋值为相同类型的的函数值。

var mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
  var result = source.search(subString);
  if (result == -1) {
    return false;
  }
  else {
    return true;
  }
}

在函数类型正确的通过类型检查中,参数的名称不是必须匹配的。例如,上面的例子我们可以这样写:

var mySearch: SearchFunc;
mySearch = function(src: string, sub: string) {
  var result = src.search(sub);
  if (result == -1) {
    return false;
  }
  else {
    return true;
  }
}

函数参数一次只检查一个,相互检查每个位置对应参数的类型。在这里,我们的函数表达式的返回类型被它返回的值所表明(这里的false和true)。假如函数表达式返回的是number或者string,那么类型检查器将会通过返回类型与"SearchFunc" interface的描述类型不符用来警告我们。

数组类型
与我们使用interface来描述函数类型一样,我们也可以用interface来描述数组类型。数组类型有一个"index"类型用来描述了数组索引的类型,以及一个返回值类型用来表示相对应索引的元素类型。

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

支持的两种索引类型:string和number。数组可以同时使用这两种索引类型。但也存在限制,数字索引的返回值类型必须是字符串索引返回值类型的子类型。

interface Something {
    [index: string]: number;
    [index: number]: number;  //数字索引的返回值类型是number,它是字符串索引的返回值类型的子类型;若[index: string]:string,则数字索引的返回值类型也必须是string
}

虽然索引标识是个用来描述数组及"dictionary"模式的很好的方式,同时也迫使所有属性需要匹配他们的返回类型。在这个例子中,属性类型与索引类型不匹配,类型检查程序给出错误:

interface Dictionary {
  [index: string]: string;
  length: number;    // 错误, ‘length‘的类型不是索引类型的子类型
} 

类类型
实现接口
在C#和Java中,接口最基础的用法是用来强制让类去符合某种特定的规则,而在TypeScript中也可以这样做。

interface ClockInterface {
    currentTime: Date;
}
class Clock implements ClockInterface  {
    currentTime: Date;
    constructor(h: number, m: number) { }
}

你也可以在接口中描述方法,然后在类中实现这个方法,就像我们下面例子中的"setTime":

interface ClockInterface {
    currentTime: Date;
    setTime(d: Date);
}
class Clock implements ClockInterface  {
    currentTime: Date;
    setTime(d: Date) {
        this.currentTime = d;
    }
    constructor(h: number, m: number) { }
}

接口描述了类的公有部分,而非公有和私有两部分。使用它们来检查一个类的实例的私有部分所含的特殊类型是行不通的。

类的静态部分和实例部分的差异
当处理类和接口的时候,你需要记住类有两种类型:静态的类型和实例的类型。你可能注意到了,如果你创建一个带有构造签名的接口并尝试创建一个用来实现这个接口的类的时候,会产生一个错误:

interface ClockInterface {
    new (hour: number, minute: number);
}
class Clock implements ClockInterface  {
    currentTime: Date;
    constructor(h: number, m: number) { }
}
// 错误信息: Class ‘Clock‘ incorrectly implements interface ‘ClockInterface‘

这是因为当用一个类来实现一个接口时,只检查该类的实例部分。由于构造函数位于静态部分,它不包含在该检查中。
所以,我们需要直接来操作类的静态部分。在这个例子中,我们直接与该类进行操作:

interface ClockStatic {
    new (hour: number, minute: number);
}
class Clock  {
    currentTime: Date;
    constructor(h: number, m: number) { }
}
var cs: ClockStatic = Clock;
var newClock = new cs(7, 30);

接口扩展
和类一样,接口也可以彼此间进行扩展。这个处理的任务是将一个接口的成员复制到另一个接口中,这样就可以更自由地把接口分离成可复用的组件。

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

一个接口可以扩展多个接口,创建出一个包含所有接口的组合接口。

interface Shape {
    color: string;
}
interface PenStroke {
    penWidth: number;
}
interface Square extends Shape, PenStroke {
    sideLength: number;
}
var square = <Square>{};
square.color = "blue";
square.sideLength = 10;
square.penWidth = 5.0;

混合类型
正如我们之前所说,接口可以描述JavaScript世界里的丰富类型。因为JavaScript的动态的和灵活特性,你可能会偶尔碰到需要一个由上述多种类型组成的对象。
下面就有这么个例子,一个对象用来当做函数和对象一起使用,并且具有附加属性。

interface Counter {
    (start: number): string;
    interval: number;
    reset(): void;
}
function counter():Counter{
    var self = <Counter>function(start:number){
        console.log("Hello World " + start);
    };
    self.interval = 10;
    self.reset = function(){
        self.interval = 10;
    }
    return self;
}
var c = counter();//c.interval = 10
c(5); //c.interval = 5
c.interval = 15; //c.interval = 15
c.reset(); //c.interval = 10

与JavaScript的第三方库交互时,您可能需要使用上述模式来全面的定义类型。

时间: 2024-08-10 13:51:27

TypeScript Interface(接口)的相关文章

TypeScript入门五:TypeScript的接口

TypeScript接口的基本使用 TypeScript函数类型接口 TypeScript可索引类型接口 TypeScript类类型接口 TypeScript接口与继承 一.TypeScript接口的基本使用 1.1定义TypeScript接口的指令(interface) 接口让我们想到的第一个短语就是(API).比如日常我们所说的调用某某程序的API一般都是跨应用的接口,如别的网站的或者APP的接口:还有我们每天都是用的编程语言的指令和内置的方法及属性,这些可以叫做编程语言的接口:还有令我们既

Interface接口的设置是由其他模块决定的

描述:我写了个登陆器   无非就是登陆和注册这2个功能,当然还有一个验证码功能 根据职责性,我登陆器不涉及任何用户有关操作. 但我需要规定用户模型必须有以下几个功能,我登陆器才能使用,登陆.注册.根据名字获取用户的个人信息. 所以我设置如下 <?php interface IMember {    /**   * 根据用户名获取用户信息 用户名不指定可以是邮箱.昵称或者手机号码   * @param String $username   */  public function getOneMem

java====interface接口

package cn.china; abstract class AbsDemo{ abstract void show1(); abstract void show2(); } /** *当一个抽象类中的方法都是抽象的时候,这时可以将该抽象类用 *另一种形式定义和表示,就是 接口 interface * *定义接口使用的关键字不是class,是interface. **/ interface Demo5{ public static final int NUMBER=4; public abs

Java知多少(39)interface接口

在抽象类中,可以包含一个或多个抽象方法:但在接口(interface)中,所有的方法必须都是抽象的,不能有方法体,它比抽象类更加“抽象”. 接口使用 interface 关键字来声明,可以看做是一种特殊的抽象类,可以指定一个类必须做什么,而不是规定它如何去做. 现实中也有很多接口的实例,比如说串口电脑硬盘,Serial ATA委员会指定了Serial ATA 2.0规范,这种规范就是接口.Serial ATA委员会不负责生产硬盘,只是指定通用的规范. 希捷.日立.三星等生产厂家会按照规范生产符合

as3.0 interface接口使用方法

[转]as3.0 interface接口使用方法 AS在2.0的时候就支持接口了 接口能够让你的程序更具扩展性和灵活性,打个例如 比方你定义了一个方法 代码: public function aMethod(arg:MyClass):void { .....} 參数 arg 的类型必须是 MyClass,由于我们须要在该方法中使用MyClass的API 而MyClass是一个类的话,你传入的对象必须是MyClass类的实例或者是MyClass子类的对象,可是当你要传入的一个对象,他既不是MyCl

golang中interface接口的深度解析

什么是interface,简单的说,interface是一组method的组合,下面这篇文章主要给大家深度解析了关于golang中的interface接口,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧. 一 接口介绍 如果说gorountine和channel是支撑起Go语言的并发模型的基石,让Go语言在如今集群化与多核化的时代成为一道亮丽的风景,那么接口是Go语言整个类型系列的基石,让Go语言在基础编程哲学的探索上达到前所

TypeScript之接口类型

Interfaces 作为TypeScript中的核心特色之一,能够让类型检查帮助我们知道一个对象应该有什么,相比我们在编写JavaScript的时候经常遇到函数需要传递参数,可能在编写的时候知道这个对象能够提供哪些值,但是以后维护的时候负责看这段代码的人都无法确认这个对象还有其他的哪些值,就需要翻阅源码看看调用这个函数的代码. 第一个接口 在开始正题之前我们先来一个简单的例子. --TypeScript 1 function printLabel(labelObject: { label: s

Interface接口

一.接口及作用 接口是一个非常重要的概念,理解这个,先举一个实现生活中的实例. 现在,电脑主板,有很多插槽,可用来插CPU.内存等.当CPU等元件需要更新换代升级时,只要将CPU单独更换就可以了,而不需要更换主板.其实,主板上的这些暴露在外的插槽,就可以理解为接口. 接口就是对外暴露的规则,只要符合规则的CPU.内存,不论品牌.型号.规格,都可以安插使用. 接口是程序的功能扩展.有了插槽,也就提高了主板的功能扩展性,比如内存不够用了,我们就可以换成内容最大的内存条,或再加新的内存条. 接口降低了

Adapter适配器中通过Interface接口响应回调

//回调接口 public interface BottomCallBackInterface {     public interface OnBottomClickListener {         void onBottomClick(View v, int position);     } } //适配器中引用该方法 private OnBottomClickListener mListener; public WaitTakingAdapter(Context context, Li