精进TypeScript--你了解类型(type)和接口(interface)的区别吗?

2024-04-04 08:36

本文主要是介绍精进TypeScript--你了解类型(type)和接口(interface)的区别吗?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

要记住的事情:

  • 理解 type 和 interface 之间的异同
  • 知道如何使用其中一种语法来编写相同的类型
  • 当决定在你的项目中使用哪一种语法时,既要考虑既定的风格,也要考虑扩增是否会有好处

如果你想在 TypeScript 中定义一个命名类型,你有两种选择,使用一个类型或接口,如下:

type TState = {name: string;capital: string;
}interface IState {name: string;capital: string;
}

你应该使用哪个?你应该意识到 type 和 interface 之间的区别,并且在哪种情况下使用哪一种都要保持一致。但是,你也应该知道如何使用这两种方式来编写相同的类型,这样你就能自如地读懂使用这两种编写的 TypeScript 代码。

首先,关于相似性:State 类型之间几乎没有区别。不管你用 IState 还是 TState 定义了一个带有多余属性的值,你得到的错误是字对字相同的:

const state: TState = {name: 'China';capital: 'BeiJing';population: 5000000; // ~~ 不能将类型 ... 分配给类型 “TState”
}

你可以对 interface 和 type 使用索引签名:

type TDict = {[key: string]: string};
interface IDict {[key: string]: string;
}

你也可以用它们中的任意一个定义函数类型:

type TFn = (x: number) => string;
interface IFn {(x: number): string;
}const toStrT: TFn = x => '' + x; // OK
const toStrI: IFn = x => '' + x; // OK

对于这种直接的函数类型,类型别名看起来更自然,但如果函数类型也具有属性,那么声明看起来就更相似。

type TFnWithProperties = {(x: number): number;prop: string;
}
interface IFnWithProperties {(x: number): number;prop: string;
}

你可以通过提醒自己,在JavaScript 中,函数是可调用的对象,来记住这种语法。

类型别名和接口都可以是泛型:

type TPair<T> = {first: T;second: T;
}interface IPair<T> = {first: T;second: T;
}

interface 可以扩展 type,type 也可以扩展 interface:

interface IStateWithPop extends TState {population: number;
}
type TStateWithPop = IState & {population: number;}

同样,这两个类型都是相同的。需要注意的是,interface 不能扩展复杂的类型,如联合类型。如果你想这么做,你需要使用 type 和 &。

类(class)可以实现interface或简单类型:

class StateT implements TState {name: string = '';capital: string = '';
}
class StateI implements IState {name: string = '';capital: string = '';
}

这些是相似之处。那不同之处呢?你已经看到了一个:有联合 type,但没有联合 interface:

type A or B = 'a' | 'b';

扩展联合类型是很有用的。如果你有单独的 Input 和 Output 变量的类型,以及从名字(name)到变量的映射:

type Input = { /*...*/ };
type Output = { /*...*/ };
interface VariableMap {[name: string]: Input | Output;
}

那么你可能想要一个将名字(name)附加到变量上的类型,如:

type NamedVariable = (Input | Output) & {name: string};

这个类型无法用 interface 来表达。一般来说,type 比 interface 能力更强。类型可以是一个联合类型,也可以利用更高级的特性,如映射类型(mapped)和条件类型(conditional)。

它还可以更容易地表达元组和数组类型:

type Pair = [number, number];
type StringList = string[];
type NamedNums = [string, ...number[]];

你可以用 interface 来表达类似元组的东西:

interface Tuple {0: number;1: number;length: 2;
}
const t: Tuple = [10, 20]; // OK

但这很笨拙,而且放弃了所有的元组方法,如 concat,所以最好使用 type。

不过,interface 确实有一些 type 没有的能力。其中之一就是 interface 可以被扩增。比如:

interface IState {name: string;capital: string;
}
interface IState {population: number;
}
const state: IState = {name: 'China';capital: 'BeiJing';population: 5000000;
}; // OK

这就是所谓的 “声明合并” ,如果你从来没见过这种写法,它会让你很惊讶。它主要用于类型声明文件,如果你正在编写一个类型声明文件,你就应该遵循该规范,并使用 interface 来支持它。这样做,是因为你的类型声明中可能会缺少一些需要用户补充的属性,这时候用户就会使用声明合并。

对于没有既定风格的项目,你应该考虑扩增。你是否在为一个 API 发布类型声明?如果 API 发生变化时,能够通过 interface 合并新的字段可能对你的用户有帮助,那就使用 interface。但是,对于一个在你项目内部使用的类型,声明合并可能是一个错误,那就倾向于使用 type。

这篇关于精进TypeScript--你了解类型(type)和接口(interface)的区别吗?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/875310

相关文章

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

native和static native区别

本文基于Hello JNI  如有疑惑,请看之前几篇文章。 native 与 static native java中 public native String helloJni();public native static String helloJniStatic();1212 JNI中 JNIEXPORT jstring JNICALL Java_com_test_g

自定义类型:结构体(续)

目录 一. 结构体的内存对齐 1.1 为什么存在内存对齐? 1.2 修改默认对齐数 二. 结构体传参 三. 结构体实现位段 一. 结构体的内存对齐 在前面的文章里我们已经讲过一部分的内存对齐的知识,并举出了两个例子,我们再举出两个例子继续说明: struct S3{double a;int b;char c;};int mian(){printf("%zd\n",s

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

flume系列之:查看flume系统日志、查看统计flume日志类型、查看flume日志

遍历指定目录下多个文件查找指定内容 服务器系统日志会记录flume相关日志 cat /var/log/messages |grep -i oom 查找系统日志中关于flume的指定日志 import osdef search_string_in_files(directory, search_string):count = 0

两个月冲刺软考——访问位与修改位的题型(淘汰哪一页);内聚的类型;关于码制的知识点;地址映射的相关内容

1.访问位与修改位的题型(淘汰哪一页) 访问位:为1时表示在内存期间被访问过,为0时表示未被访问;修改位:为1时表示该页面自从被装入内存后被修改过,为0时表示未修改过。 置换页面时,最先置换访问位和修改位为00的,其次是01(没被访问但被修改过)的,之后是10(被访问了但没被修改过),最后是11。 2.内聚的类型 功能内聚:完成一个单一功能,各个部分协同工作,缺一不可。 顺序内聚:

Java 后端接口入参 - 联合前端VUE 使用AES完成入参出参加密解密

加密效果: 解密后的数据就是正常数据: 后端:使用的是spring-cloud框架,在gateway模块进行操作 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.0-jre</version></dependency> 编写一个AES加密

Android fill_parent、match_parent、wrap_content三者的作用及区别

这三个属性都是用来适应视图的水平或者垂直大小,以视图的内容或尺寸为基础的布局,比精确的指定视图的范围更加方便。 1、fill_parent 设置一个视图的布局为fill_parent将强制性的使视图扩展至它父元素的大小 2、match_parent 和fill_parent一样,从字面上的意思match_parent更贴切一些,于是从2.2开始,两个属性都可以使用,但2.3版本以后的建议使

Mysql BLOB类型介绍

BLOB类型的字段用于存储二进制数据 在MySQL中,BLOB类型,包括:TinyBlob、Blob、MediumBlob、LongBlob,这几个类型之间的唯一区别是在存储的大小不同。 TinyBlob 最大 255 Blob 最大 65K MediumBlob 最大 16M LongBlob 最大 4G