TypeScript之接口类型

Interfaces

作为TypeScript中的核心特色之一,能够让类型检查帮助我们知道一个对象应该有什么,相比我们在编写JavaScript的时候经常遇到函数需要传递参数,可能在编写的时候知道这个对象能够提供哪些值,但是以后维护的时候负责看这段代码的人都无法确认这个对象还有其他的哪些值,就需要翻阅源码看看调用这个函数的代码。

第一个接口

在开始正题之前我们先来一个简单的例子。

--TypeScript

1 function printLabel(labelObject: { label: string }) {
2     console.log(labelObject.label);
3 }
4
5 var myobj = { size: 10, label: "Size 10 Object" };
6 printLabel(myobj);

--JavaScript

function printLabel(labelObject) {
    console.log(labelObject.label);
}

var myobj = { size: 10, label: "Size 10 Object" };
printLabel(myobj);

类型检查会在我们调用printLabel的时候检查传进去的参数,确保该参数中存在一个名字为label并且类型为string的属性,当然我们可以看到这个参数的值远远比我们函数要求的多,但这并不会造成影响,通过最终的源码我们也可以看到最终生成的js代码并没有比原来多出多少,但是却能够为我们提供强大的类型检查。

下面我们可以引入正题了,我们将使用接口的方式实现上面的例子。

--TypeScript

 1 interface LabelledValue {
 2     label: string
 3 }
 4
 5 function printLabel(labelObject: LabelledValue) {
 6     console.log(labelObject.label);
 7 }
 8
 9 var myobj = { size: 10, label: "Size 10 Object" };
10 printLabel(myobj);

--JavaScript

同上

这里我们看到如果利用接口能够更便于管理,更主要的是接口中除了可以定义属性也可以定义函数等,对于中大型项目,特别是前后端分离的网站来说对于以后的维护和迭代能顾节省时间成本并提高质量。

可选属性

但是由于历史原因,TypeScript并不能孤立存在,还是需要兼容其他库,那么就导致我们的接口还要考虑另一种情况就是可选值,比如下面这个例子。

--TypeScript

 1 interface SquareConfig {
 2     color?: string;
 3     width?: number;
 4 }
 5
 6 function createSquare(config: SquareConfig): { color: string; area: number } {
 7     var newsquare = { color: "white", area: 100 };
 8     if (config.color) {
 9         newsquare.color = config.color;
10     }
11     if (config.width) {
12         newsquare.area = config.width * config.width;
13     }
14     return newsquare;
15 }
16
17 var mySquare = createSquare({ color: "black" });

--JavaScript

 1 function createSquare(config) {
 2     var newsquare = { color: "white", area: 100 };
 3     if (config.color) {
 4         newsquare.color = config.color;
 5     }
 6     if (config.width) {
 7         newsquare.area = config.width * config.width;
 8     }
 9     return newsquare;
10 }
11
12 var mySquare = createSquare({ color: "black" });

通过接口我们知道可选属性就是在属性名称的后面加上问号就可以了,但是开发的时候要注意就是要通过if判断下该值是否存在。

函数类型

玩转了属性,下面我们开始在接口中放入函数,下面我们先放一个函数。

--TypeScript

 1 interface SearchFunc {
 2     (source: string, substring: string): boolean;
 3 }
 4
 5 var mySearch: SearchFunc;
 6 mySearch = function (source: string, substring: string) {
 7     var result = source.search(substring);
 8     if (result == -1) {
 9         return false;
10     } else {
11         return true;
12     }
13 };

--JavaScript

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

大家肯定会很奇怪,下面为什么定义了这个接口的变量但是赋的确是一个函数,如果大家有C#和java语言的基础会发现SearchFunc中的函数是没有函数名的,所以mySearch的类型就是一个函数,只是会进行类型检查,你是不能赋其他函数签名不一样的函数给他的。

数组类型

接口除了可以描述函数类型也可以描述数组类型,数组类型拥有一个“index”类型,是用来索引数组的,利用这个我们就可以实现除了数组以外还能够实现字典类型。

--TypeScript

1 interface StringArray {
2     [index: number]: string;
3 }
4
5 var myArray: StringArray;
6 myArray = ["Bob", "Fred"];

--JavaScript

1 var myArray;
2 myArray = ["Bob", "Fred"];

Index类型能够支持两种类型:string和number,所以我们能够实现字典类型,比如下面这种类型。

--TypeScript

1 interface StringArray {
2     [index: string]: string;
3 }
4
5 var myArray: StringArray;
6 myArray = {
7     "dede": "dede",
8     "ete":"dede"
9 };

--JavaScript

1 var myArray;
2 myArray = {
3     "dede": "dede",
4     "ete": "dede"
5 };

类类型

像C#和Java语言中一样,接口最基础的作用就是让类去实现接口,所以这也是TypeScript语言的特点之一。比如下面的例子我们将实现一个带有一个属性的接口。

--TypeScript

1 interface ClockInterface {
2     currentTime: Date
3 }
4
5 class Clock implements ClockInterface {
6     currentTime: Date;
7     constructor(h: number, m: number) { }
8 }

--JavaScript

1 var Clock = (function () {
2     function Clock(h, m) {
3     }
4     return Clock;
5 })();

这里我们可以看到最终的JS中并没有将currentTime作为变量加入到this中,因为在这个类中我们并没有使用到这个值,所以这个变量只会在我们正式的使用的时候添加到这个类中,如果不用这个类就等同于没有这个变量。

上面我们仅仅只是在接口中写了一个属性,下面我们在接口中增加一个方法。

--TypeScript

 1 interface ClockInterface {
 2     currentTime: Date;
 3     setTime(d: Date);
 4 }
 5
 6 class Clock implements ClockInterface {
 7     currentTime: Date;
 8     setTime(d: Date) {
 9         this.currentTime = d;
10     }
11     constructor(h: number, m: number) { }
12 }

--JavaScript

1 var Clock = (function () {
2     function Clock(h, m) {
3     }
4     Clock.prototype.setTime = function (d) {
5         this.currentTime = d;
6     };
7     return Clock;
8 })();

静态类和实例类的区别

当我们使用类和接口,需要知道类是存在静态和实例的,这也就意味着如果你的接口如果存在构造方法并且需要一个类去实现,那么你将会看到错误信息,比如下面这段。

--TypeScript

1 interface ClockInterface {
2     new (hour: number, minute: number);
3 }
4
5 class Clock implements ClockInterface {
6     currentTime: Date;
7     constructor(h: number, m: number) { }
8 }

这是因为当一个类实现一个接口的时候只有实例部分是被允许的,而构造方法恰恰属于静态,并不包含在内。

当然含有构造方法的接口是有其用途的,比如下面这样的用法。

--TypeScript

 1 interface ClockInterface {
 2     new (hour: number, minute: number);
 3 }
 4
 5 class Clock {
 6     currentTime: Date;
 7     constructor(h: number, m: number) { }
 8 }
 9
10 var cs: ClockInterface = Clock;
11 var newClock = new cs(2, 3);

--JavaScript

1 var Clock = (function () {
2     function Clock(h, m) {
3     }
4     return Clock;
5 })();
6
7 var cs = Clock;
8 var newClock = new cs(2, 3);

扩展接口

这个特性跟类可以继承其他类一样,接口也可以扩展其他的接口,这将会导致被继承的接口中的所有的内容都会被复制到另一个接口中。下面我们来看一个简单的例子。

--TypeScript

 1 interface Shape {
 2     color: string;
 3 }
 4
 5 interface Square extends Shape {
 6     sideLength: number;
 7 }
 8
 9 var square = <Square>{};
10 square.color = "blue";
11 square.sideLength = 10;

--JavaScript

1 var square = {};
2 square.color = "blue";
3 square.sideLength = 10;

一个接口不仅仅只能扩展一个接口,是可以扩展多个接口的。比如下面这样。

--TypeScript

 1 interface Shape {
 2     color: string;
 3 }
 4
 5 interface PenStroke {
 6     penWidth: number;
 7 }
 8
 9 interface Square extends Shape, PenStroke {
10     sideLength: number;
11 }
12
13 var square = <Square>{};
14 square.color = "blue";
15 square.sideLength = 10;
16 square.penWidth = 5.0;

--JavaScript

1 var square = {};
2 square.color = "blue";
3 square.sideLength = 10;
4 square.penWidth = 5.0;

混合类型

我们再次之前提到过,接口可以描述很多真实世界中JavaScript的类型,因为JavaScript的动态和天生的灵活性,你或许会遇到一些需要多种复合的类型。

比如下面的实例,这个对象将扮演着函数和一个对象。

--TypeScript

 1 interface Counter {
 2     (start: number): string;
 3     interval: number;
 4     reset(): void;
 5 }
 6
 7 var c: Counter;
 8 c(10);
 9 c.reset();
10 c.interval = 5.0;

--JavaScript

1 var c;
2 c(10);
3 c.reset();
4 c.interval = 5.0;

对于需要使用第三方JavaScript库的情况下,我们就会需要使用到上面介绍的知识。当然现在很多常用的JavaScript库都已经存在了,我们可以通过nuget获取到。

时间: 2024-10-12 08:13:43

TypeScript之接口类型的相关文章

TypeScript学习笔记之接口类型

TypeScript的接口,个人理解就是一种约束,包括各种类型的契约或者代码定义上的契约.当然,和java中的用法基本一致,接口可以被继承也可以被实现. 定义一个简单的interface interface LabelledValue { label: string; } function printLabel(labelledValue: LabelledValue) { console.log(labelledValue.label); } let myLabel: LabelledValu

TypeScript入门五:TypeScript的接口

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

混合调用时接口类型中的陷阱

[delphi] view plain copy function abc(A: Integer): IUnknown; 这是一个Delphi的函数声明,看上去很简单,只有一个参数而已,但是真实情况呢?在编译成二进制代码后,实际上函数的参数已经有2个了! 为了更详细的说明问题,先用Delphi写一个DLL,导出一个接口,接口有一个Show方法. [delphi] view plain copy library Project1; uses Windows; {$R *.res} type ITe

【Go语言】【14】GO语言的接口类型

1.什么是接口? 在面向对象的语言中,接口是用来限制实现类行为的.怎么理解这句话呢? 定义一个Person接口,我只会站在我的角度上考虑问题,比如Person(人),自然想到会吃饭.睡觉等: interface Person { // 人会吃饭 void eat(); // 人会睡觉 void sleep(); } 我是站在接口角度上考虑接口如何定义,此时不会过多考虑实现类的行为. 这很正常,因为我不能确定谁会使用我的接口,有一天SuperMan说:"我要用你定义的接口",那Super

无法将类型为“Microsoft.Office.Interop.Word.ApplicationClass”的 COM 对象强制转换为接口类型“Microsoft.Office.Interop.Word._Application”。

无法将类型为“Microsoft.Office.Interop.Word.ApplicationClass”的 COM 对象强制转换为接口类型“Microsoft.Office.Interop.Word._Application”.此操作失败的原因是对 IID 为“{00020970-0000-0000-C000-000000000046}”的接口的 COM 组件调用 QueryInterface 因以下错误而失败: 加载类型库/DLL 时出错. (异常来自 HRESULT:0x80029C4A

SDH接口类型

2M SDH电路有哪几种接口类型? 主要有三种: G.703.V.35以及以太网接口,这样就要求客户端的路由设备需要具有对应的接口

[转]电脑显卡4种接口类型:VGA、DVI、HDMI、DP

电脑显卡全称显示接口卡(Video card,Graphics card),又称为显示适配器(Video adapter),是个人电脑最基本组成部分之一.对于显卡接口类型,主要包括VGA.dvi.HDMI.dp这四种比较常见的接口,当然还有其他的. VGA接口是最常见,也就是我们通常的电脑显示器连接主机的那种,VGA接口是一种D型接口,上面共有15针,分成三排,每排五个.并且VGA接口扩展性比较强,可以轻松与DVI接口进行转换,VGA接口介绍如下图: 通过上面介绍了VGA接口包括15个针脚,那么

C#WPF无法将类型为“System.__ComObject”的 COM 对象强制转换为接口类型“System.Speech.Internal.SapiInterop.ISpDataKey”。解决办法

this.speecher.SpeakAsync(textToSpeak); // 报错 无法将类型为"System.__ComObject"的 COM 对象强制转换为接口类型"System.Speech.Internal.SapiInterop.ISpDataKey".此操作失败的原因是对 IID 为"{14056581-E16C-11D2-BB90-00C04F8EE6C0}"的接口的 COM 组件调用 QueryInterface 因以下错

关于java中任意对象强制转换为接口类型的问题

java中任意对象强转为接口类型都不会有编译错误 public class Apple implements Eatable{ public static void main(String args[]) { Drinkable drinkable = (Drinkable)new Apple(); } } interface Eatable{} interface Drinkable{} java中的类可以多实现接口,Java编译器无法判断该类是否实现了该接口所以不会有编译错误. 但是Java