TypeScript 中的类和接口

在面向对象(OOP)编程中,经常会使用到class(类)和interface(接口)。在TypeScript(以下简称TS)中也引入了类和接口的概念,使得TS强大的类型检测机制更加完善。就像我们所知道的,一个类是一堆抽象概念的集合,我们可以从类的构造方法中创建出享有共同属性和方法的对象。一个接口所描述的是一个对象相关的属性和方法,但并不提供具体创建此对象实例的方法。

我们的前端项目使用Angular2.0+作为技术栈,Angular2.0+基于TS实现,我们在对代码中某些部分添加类型注释的时,经常出现会面对这样的问题:

"我应该使用接口还是类来对当前数据进行类型注释?"

Some Example

在开发过程中经常会有这样的操作

fetch(‘https://xxx.com/api/blabla‘)

.then(data => {

console.log(data); // data: any

});

以上代码片段向后端API发起请求,得到返回的数据后我们会在前端UI中使用。

如果我们让TS编译目前这段代码,then方法中的data参数将会默认被定义为any类型。因为在没有类型定义的情况下,TS仅仅是通过分析代码,判断出类型应该是什么。

在这种情况下,我们为了提高程序的类型安全性,我们希望能够主动地添加一个类型注释`Response`,以便告知TS编译器我们期望当前res参数的类型为什么。

// 需要在此处定义一个 `Response` 类型

fetch(‘https://xxx.com/api/blabla‘)

.then((data: Response) => {

console.log(data) // data: Response

})

由此,我们引出了本篇文章的核心问题,我们应该把`Response`类型定义为interface还是一个class呢?总感觉class和interface都可以。

TS中的interface

TS的核心原则职之一就是类型检查,关注定义的值的数据结构

interface是仅存在于TS上下文中的一种虚拟结构,TS编译器依赖接口用于类型检查,最终编译为JS后,接口将会被移除。

interface MyInterface {

a: number;

b: string;

}

以上MyInterface这个接口约定对象只能存在且必须有两个属性,这两个属性分别为数字 `a` 和 字符串 `b`,只要不遵守此约定,TS就会抛出错误。

TS中的class

与其他语言相比,JS并没有直接对类的描述,基于原型的继承方式也让众多的OOP世界的程序员充满困惑,一直到了ES6,class关键字作为一种语法糖出现。

与interface不同,class作为TS的一种变量类型存在于上下文之中,class中可以提供,变量、方法等的具体实现方式等,它的作用不仅仅是约束数据结构。

class MyClass {

a: number;

b: string;

constructor(options: MyInterface) {

this.a = options.a;

this.b = options.b;

}

foo(): void {

console.log(this.a);

console.log(this.b);

}

}

以上MyClass类定义了两个变量和一个foo方法,constructor方法会接受options参数初始化类中的属性。

class和interface的比较

在TS中class和interface都可以用来约束数据的结构,但是频繁使用class约束数据结构会使程序的性能受到影响,在 [typescript官网](https://www.tslang.cn/play/index.html) 的练习板块中,我们在左边书写TS代码,右边会显示所转换成的JS代码。

我们尝试书写class和interface看看两者转换后的代码

我们可以发现class编译了大量代码,但是interface并没有转换成任何JS,当我们定义大量的class,并且还有着复杂的继承关系时,编译过后的代码体积将更加庞大。

最佳实践

由于考虑到class和interface在TS中编译结果的不同,我们面对不同的场景,使用正确的约束数据类型的方式,对我们代码性能层面的提高就尤为重要。

什么时候使用class

当需要使用class时,我通常会考虑三个方面

  • 是否需要创建多个实例
  • 是否需要使用继承
  • 是否需要特定的单例对象

什么时候使用interface

对于从服务器端获取或者业务场景中模拟的数据,提倡使用interface去定义,这些数据通常是不会经常变化和调整的,这些数据可能仅仅只表示某些状态,或者是UI上的文本。

interface配合class

class MyClass {

a: number;

b: string;

origin: MyInterface;

constructor(options: MyInterface) {

this.a = options.a;

this.b = options.b;

this.origin = options; // 保存原始的options数据

}

foo(): void {

console.log(this.a);

console.log(this.b);

}

}

const a = new MyClass(options);

const b = new MyClass(a.origin);

在实际场景中,我们可以给class的参数指定好interface类型用来初始化class中的属性,以上代码在class的origin属性中保存了options的数据,可以用来之后初始化全新的class实例,这解决了class实例在变化后很难clone出全新实例的问题,上面实例中 `b`变量 由 `a`变量 的orgin字段初始化。

总之,当我们只是想要在TS中约束数据类型时,我们需要结合实际的场景去选择使用class还是interface,如果只是一个简单的后端请求,却都使用class去约束,想象一下编译出来一大堆无用的js代码,简直可怕ヽ(*。>Д<)o゜

原文地址:https://www.cnblogs.com/Qingflow/p/10929254.html

时间: 2024-10-13 19:35:57

TypeScript 中的类和接口的相关文章

从人类社会的角度看OO社会中的类、接口、抽象类

引言 在OO的工作中,我们一定会涉及到类,抽象类和接口.那么类和抽象类以及接口到底扮演的什么角色? 本文主要是从人类社会的角度阐述类与抽象类以及接口的“社会”关系,从而让我们抛弃书上的那些死记硬背的概念,快速理解他们的区别与联系? 如果大家觉得还有必要把这块更新的更好,还请多多反馈. 如果觉的对您有用还请点击 “推荐”下,我会持续更新更多新的内容. 古老的传说 相传盘古开天劈地后,女娲一天在黄河边梳头时,突发奇想以泥土仿照自己抟土造人,创造并构建人类社会.后来又替人类立下了婚姻制度,经过一代又一

Java中的类和接口

类有两种: 普通类  : 抽象类(abstract): 抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量.成员方法和构造方法的访问方式和普通类一样. 由于抽象类不能实例化对象,所以抽象类必须被继承(extends),才能被使用.也是因为这个原因,通常在设计阶段决定要不要设计抽象类. 父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法. 在Java中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口. 抽象方法 如果你想设计这样

Scala中的类、接口及协变和逆变

 4.   OOP 4.1.     类class 4.1.1.  定义 例子1: class User { var name = "anonymous" var age:Int = _ val country = "china" def email = name + "@mail" } 使用: val u = new User // var定义的属性可读可写 u.name = "qh"; u.age = 30 print

Typescript中的类

1 类的定义 2 类的继承 注意:一个类只能继承一个父类,这和接口有别 3 类的修饰符 请注意子类要获取父类的私有属性,要用super调用父类方法间接获取 (用this关键字调用从父类继承下来的方法同样有效,前提是用this调用的这个父类方法没有被子类重写覆盖掉) 4 类中的静态属性和静态方法 5 多态的展现 => 抽象类的多继承 关键字:abstract 注意点:具体类必须实现继承的抽象类的所有抽象化的属性和方法,如果该类没有实现所有的抽象属性和方法,就只能将其再次定义成一个抽象类,后面再写实

golang中的类和接口的使用

类使用:实现一个people中有一个sayhi的方法调用功能,代码如下: type People struct { //.. } func (p *People) SayHi() { fmt.Println("************************* say hi !!") } func (this *LoginController) Get() { p := new(People) p.SayHi() this.TplName = "login.html"

TypeScript学习笔记(四) - 类和接口

本篇将介绍TypeScript里的类和接口. 与其他强类型语言类似,TypeScript遵循ECMAScript 2015标准,支持class类型,同时也增加支持interface类型. 一.类(class) 下面是一个类的基本定义方式: 1 class User { 2 name: string; 3 constructor(_name: string) { 4 this.name = _name; 5 } 6 7 sayHello(): string { 8 return `Hello,${

JavaWeb中使用到的类与接口整理(一)servlet包

javaweb学了半本,整理了一下Servlet技术模型.servlet容器模型.jsp技术模型中的类与接口,有助于理解web应用中的页面跳转和参数传递,目录: HttpServlet 可作Scope的类(PageContext.HttpServletRequest.HttpSession.ServletContext) 其他在servlet中使用到的类(RequestDispatcher.ServletInputStream.HttpServletPesponse) HttpServlet 可

类和接口

类和接口 本篇将介绍TypeScript里的类和接口. 与其他强类型语言类似,TypeScript遵循ECMAScript 2015标准,支持class类型,同时也增加支持interface类型. 一.类(class) 下面是一个类的基本定义方式: 1 class User { 2 name: string; 3 constructor(_name: string) { 4 this.name = _name; 5 } 6 7 sayHello(): string { 8 return `Hel

(原创)c#学习笔记09--定义类01--c#中的类定义

第九章 定义类 本章内容: ●  如何在C#中定义类和接口 ●  如何使用控制可访问性和继承的关键字 ●  System.Object类及其在类定义中的作用 ●  如何使用VS和VCE提供的一些帮助工具 ●  如何定义类库 ●  接口和抽象类的异同 ●  结构类型的更多内容 ●  复制对象的一些重要信息 9.1  C#中的类定义 C#使用class关键字来定义类: class MyClass { // Class members. } 默认情况下,类声明为内部的,即只有当前项目中的代码才能访问它