TypeScript 中的类和接口

Easter79
• 阅读 848

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

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

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

一个例子

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

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゜

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
java8新特性
Stream将List转换为Map,使用Collectors.toMap方法进行转换背景:User类,类中分别有id,name,age三个属性。List集合,userList,存储User对象1、指定keyvalue,value是对象中的某个属性值。 Map<Integer,StringuserMap1userList.str
Wesley13 Wesley13
3年前
Java日期时间API系列31
  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前
Stella981 Stella981
3年前
Egret 类的创建和继承
classtestextendsegret.DisplayObjectContainer{/类的创建///属性name:string;age:number;ts:test;//可传参的构造方法publicconst
Stella981 Stella981
3年前
Javascript定义类(class)的三种方法
在面向对象编程中,类(class)是对象(object)的模板,定义了同一组对象(又称"实例")共有的属性和方法。Javascript语言不支持"类",但是可以用一些变通的方法,模拟出"类"。一、构造函数法这是经典方法,也是教科书必教的方法。它用构造函数模拟"类",在其内部用this关键字指代实例对象。  function
Wesley13 Wesley13
3年前
Java总论及三大特性理解
1、对象(object)   万物皆为对象(根类Object类)。   程序是对象的集合(面向对象程序设计语言OOP)。   每个对象都有自己的由其他对象所构成的存储(对象有成员属性)。   每个对象都拥有其类型(每个对象都是某个类class的一个实例instance)。某一特定类型的所有对象都可以接收
Wesley13 Wesley13
3年前
Java反射机制详解
一、内容提要:  1、反射机制是什么  2、反射机制能做什么  3、反射机制相关的API  4、通过一个对象获得完整的包名和类名  5、实例化Class类对象  6、获取一个对象的父类与实现的接口  7、获取某个类的全部构造函数  8、通过反射机制实例化一个类的对象  9、获取某个类的全部属性  10、
小万哥 小万哥
1年前
Python 面向对象编程:类、对象、初始化和方法详解
Python是一种面向对象的编程语言。在Python中,几乎所有东西都是对象,都具有其属性和方法。类似于对象构造函数或用于创建对象的“蓝图”的类。创建一个类要创建一个类,请使用关键字class:示例,创建一个名为MyClass的类,其中包含一个名为x的属性
小万哥 小万哥
2个月前
Kotlin 面向对象编程 (OOP) 基础:类、对象与继承详解
面向对象编程(OOP)是一种编程范式,它通过创建包含数据和方法的对象来组织代码。相较于过程式编程,OOP提供了更快更清晰的结构,有助于遵守DRY(Don&39;tRepeatYourself)原则,使代码更易于维护和扩展。在Kotlin中,类和对象是OOP的核心。类作为对象的模板,定义了对象的行为和状态;对象则是类的具体实例。例如,Car类可以定义汽车的品牌、型号等属性,以及如驾驶和刹车等功能。通过构造函数可以快速初始化对象的属性。此外,Kotlin支持继承机制,子类可以从父类继承属性和方法,促进代码重用。
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k