关于TypeScript Interface你需要知道的10件事

图片

TypeScript接口的10种使用场景——可能只有20%的web开发人员完全掌握它们

TypeScript中的接口是一个非常灵活的概念。除了抽象类的部分行为外,它还经常用于描述“对象的形状”。

必需的属性
 

在定义接口时,需要使用 interface 关键字:

interface User {  name: string;  sex: string;}​​​
const user: User = {  name: "Bytefer",  sex: "male",};

在上面的代码中,我们定义了一个 User 接口。然后定义一个 user 变量,并将其类型设置为 User 类型。但是,如果给 user 变量赋值时如果缺少相关的属性,TypeScript编译器会提示相关的错误。例如,在下面的代码中,我们在赋值时缺少 sex 属性:

图片

那么如何解决上述错误呢? 解决方案之一是在定义接口时使用 ? 声明一些属性是可选的。


可选属性

interface User {  name: string;  sex?: string;}
let user: User = { // OK  name: "Bytefer",};​​​​​user = { // Ok  name: "Bytefer",  sex: "male",};

这样在赋值是不管有没有 sex 属性就都不会报错了。

那么是否可以添加未声明的属性呢?

图片

从上图可以看出,当使用对象字面量赋值时,包括未声明的 age 属性,也会出现错误。解决这个问题最简单的方法是在 User 类型中添加 age 属性:

interface User {  name: string;  sex?: string;  age: number;}

虽然这种解决方案可以解决问题,但是如果我们想要添加其他任意属性,这种方式就不是很好了。为了满足上述要求,我们可以使用索引签名。

索引签名
 

索引签名的语法如下:

图片

键的类型只能是字符串、数字、符号或模板文字类型,而值的类型可以是任何类型。

图片

现在我们理解了索引签名的语法,让我们来更新 User 类型:

interface User {  name: string;  sex?: string;  [propName: string]: any; // Index Signatures}

在更新了 User 类型,并添加了新的 age 和 email 属性之后,TypeScript编译器就不会提示错误了。

let user: User = {  name: "Bytefer",  sex: "male",  age: 30,  email: "bytefer@gmail.com"};


只读的属性
 

在web系统中,我们需要区分不同的用户,一般来说,我们会使用 id 属性来识别不同的用户。此属性由Web系统自动生成,用户不能修改。对于上面的场景,我们可以使用 readonly 修饰符来定义只读属性。

图片

除了属性,对象还可以包含方法。当使用接口定义对象类型时,还可以声明同时存在于对象上的方法:

interface User {  id: string;  name: string;  say(words: string): void;}​​​let user: User = {  id: "6666",  name: "Bytefer",  say(words: string) {    console.log(words);  },};


调用签名
 

描述函数最简单的方法是使用函数类型表达式。这些类型在语法上类似于箭头函数:

const log: (msg: string) => void = (msg: string) => {  console.log(msg);};
log("Bytefer");

语法 (msg: string) => void 表示“具有一个名为 msg 的字符串类型参数的函数,该函数没有返回值”。当然,我们可以使用类型别名来命名函数类型:

type LogFn = (msg: string) => void;
 
const log: LogFn = (msg: string) => {  console.log(msg);};

如果我们想用属性描述一些可调用的东西,函数本身也是一个对象。那么函数类型表达式就不能满足这个要求。对于这种情况,我们可以在定义对象类型时使用调用签名:

图片

需要注意的是,在声明调用签名时,还支持重载:​​​​​​

interface Logger {  type: string;  (msg: string): void;  (msg: string, timestamp: number): void  (msg: string, timestamp: number, module: string): void}


构造签名

除了直接调用函数外,还可以使用 new 操作符来调用函数,这些函数通常称为构造函数。我们可以通过在调用签名前添加 new 关键字来编写构造签名:

interface PointConstructor {  new (x: number, y: number): { x: number; y: number };}​​​​​​function createPoint(ctor: PointConstructor,   x: number = 0, y: number = 0) {  return new ctor(x, y);}​​​​​​class Point {  
  
  constructor(public x: number, public y: number) {}}​​​​​​const zero = createPoint(Point);console.log(zero);


混合类型
 

因此,在定义接口时,我们可以同时使用调用签名和构造签名吗? 答案是肯定的,我们常用的 Date 对象,它的类型是 DateConstructor ,其中调用签名和构造签名都被使用:

declare var Date: DateConstructor;

图片

在上面的代码中,除了调用签名和构造签名之外,还定义了 Date 构造函数的属性和方法。

通用接口
 

泛型类型也可以与接口一起使用。下面是一个通用接口。

interface KeyPair<T, U> {  key: T;  value: U;}
let kv1: KeyPair<number, string> = { key: 1, value: "Bytefer" };


扩展接口

接口可以扩展一个或多个接口。这使得编写接口变得灵活和可重用。

interface Point1D {  x: number;}interface Point2D extends Point1D {  y: number;}interface Point3D extends Point2D {  z: number;}​​​​​​​const point1D = { x: 0 };const point2D = { x: 0, y: 0 };const point3D = { x: 0, y: 0, z: 0 };

除了扩展单个接口,TypeScript还允许我们扩展多个接口:​​​​​​​

interface CanSay {   say(words: string) :void }​​​​​​interface CanWalk {  walk(): void;}​​​​​​interface Human extends CanSay, CanWalk {  name: string;}


扩展类
 

在声明接口时,我们可以扩展一个或多个接口。实际上,我们也可以扩展已声明的类:​​​​​​​

class Point1D {  public x!: number;}​​​​​​interface Point2D extends Point1D {  y: number;}
const point2D: Point2D = { x: 0, y: 0 }

对于一个类,在声明该类时,可以同时实现多个接口:​​​​​​​

interface CanSay {   say(words: string) :void }​​​​​​​interface CanWalk {  walk(): void;}​​​​​​​class Person implements CanSay, CanWalk {  constructor(public name: string) {}    public say(words: string) :void {    console.log(`${this.name} says:${words}`);    }    public walk(): void {    console.log(`${this.name} walk with feet`);  }

对于TypeScript开发者来说,接口和类型有很多相似之处,当然也有一些不同之处,需要根据场景灵活运用。

 欢迎关注公众号:文本魔术,了解更多

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/292514.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

prometheus基本介绍

官网&#xff1a;https://prometheus.io/docs/introduction/overview/ 中文&#xff1a; https://www.prometheus.wang/ Prometheus 选择 Prometheus 并不是偶然&#xff0c;因为&#xff1a; • Prometheus 是按照 《Google SRE 运维之道》的理念构建的&#xff0c;具有实用…

css sourcemap 源代码映射

vue.config.js css: {// Enable CSS source maps.sourceMap: process.env.NODE_ENV ! production, }重新运行&#xff1a;yarn serve 效果&#xff1a;

基于sy3130光感入耳检测功能成功实现

基于sy3130光感入耳检测功能成功实现 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?可加我微信hezkz17, 本群提供音频技术答疑服务,+群赠送语音信号处理降噪算法,蓝牙耳机音频,DSP音频项目核心开发资料, 1 芯片介绍 2 电路实现 3 寄存器列表

部署清华ChatGLM-6B(Linux版)

引言 前段时间,清华公布了中英双语对话模型 ChatGLM-6B,具有60亿的参数,初具问答和对话功能。最!最!最重要的是它能够支持私有化部署,大部分实验室的服务器基本上都能跑起来。因为条件特殊,实验室网络不通,那么如何进行离线部署呢? 「部署环境」:CUDA Version 11.0,…

41.使用@Autowired注解自动装配的过程是怎样的?

使用@Autowired注解自动装配的过程是怎样的? 记住:@Autowired 通过Bean的后置处理器进行解析的 在创建一个Spring上下文的时候,在构造函数中进行注册AutowiredAnnotationBeanPostProcessor在Bean的创建过程中进行解析在实例化后预解析(解析@Autowired标注的属性、方法 比如…

【MySQL】数据库之MHA高可用

目录 一、MHA 1、什么是MHA 2、MHA 的组成 3、MHA的特点 4、MHA的工作原理 二、有哪些数据库集群高可用方案 三、实操&#xff1a;一主两从部署MHA 1、完成主从复制 步骤一&#xff1a;完成所有MySQL的配置文件修改 步骤二&#xff1a;完成所有MySQL的主从授权&#x…

MySQL检索距离当前最近的7个小时内,靠近每个时间点数据信息

MySQL检索距离当前最近的7个小时内&#xff0c;靠近每个时间点数据信息 如果你想在最近7个小时内找到每个时间点最接近的数据&#xff0c;即使某些时间点没有数据&#xff0c;你可以使用子查询和窗口函数。以下是一个示例查询&#xff1a; sqlCopy codeSELECTt.time_point,CO…

Hive用户自定义函数之UDF开发

在进行大数据分析或者开发的时候&#xff0c;难免用到Hive进行数据查询分析&#xff0c;Hive内置很多函数&#xff0c;但是会有一部分需求需要自己开发&#xff0c;这个时候就需要自定义函数了&#xff0c;Hive的自定义函数开发非常方便&#xff0c;今天首先讲一下UDF的入门开发…

Python初探:从零开始的编程奇妙之旅

一、Python是什么 Python是一门多用途的高级编程语言&#xff0c;以其简洁、易读的语法而脱颖而出。在深度学习领域&#xff0c;Python扮演着至关重要的角色。其丰富的科学计算库&#xff08;如NumPy、Pandas、Matplotlib&#xff09;和强大的深度学习框架&#xff08;如Tenso…

树莓派通过 I2C 驱动 LCD1602 液晶屏

前一阵用废旧的树莓派做了一个NAS服务器&#xff0c;手里还要一块闲置的LCD 1602 液晶屏模块&#xff0c;可以用来实时显示IP&#xff0c;作为NAS的服务器输出显示。 在树莓派上LCD 1602 液晶屏模块的使用非常简单&#xff0c;可以用 I2C 方式的驱动&#xff0c;只要使能0&…

【无标题】一本好书

(https://img-blog.csdnimg.cn/9e3c2302242149e4ac7dbc834bd5e027.jpg)(https://img-blog.csdnimg.cn/3427ed8648ff46bbb496ed512e0aa9cd.jpg1

2分钟了解什么是socket?

文章目录 概念比喻类型Socket 与 TCP、UDP的关系 概念 Socket 是提供网络通信功能的编程接口&#xff08;API&#xff09;&#xff0c;提供了网络通信的基本操作&#xff0c;允许程序或进程之间进行数据交换。是传输层协议的具体软件实现&#xff0c;它封装了协议底层的复杂实…

构建高效数据中台:集群规划与搭建的最佳实践指南

架构设计 Rack(机架)配置建议 大数据集群规划 安装细节见配套文档 两地三中心 两地三中心是一种信息技术架构模式,通常用于灾难恢复和业务连续性计划。这种模式设计有两个物理位置(两地),在这两个位置上部署了三个数据中心(三中心):一个主数据中心和两个备份数据中心…

docker 安装可视化工具 Portainer 以及 汉化

安装portainer是最新版本&#xff0c;汉化指定版本2.9.1 。如果要安装汉化版&#xff0c;可直接跳转步骤四 一、拉去镜像 安装网址&#xff1a;Install Portainer BE with Docker on Linux - Portainer Documentation docker pull portainer/portainer二、根据portainer镜像创建…

React Admin 前端脚手架之ant-design-pro

文章目录 一、React Admin 前端脚手架选型二、React Admin 前端脚手架之ant-design-pro三、ant-design-pro使用步骤四、常用总结&#xff08;持续更新&#xff09;EditableProTable组件 常用组件EditableProTable组件 编辑某行后&#xff0c;保存时候触发发送请求EditableProTa…

代码随想录算法训练营第五十五天|392.判断子序列、115.不同的子序列

代码随想录 (programmercarl.com) 392.判断子序列 可以不连续 类似LC1143-求最长公共子序列 1.dp数组及下标含义 dp[i][j]&#xff1a;表示以下标i-1为结尾的字符串s&#xff0c;和以下标j-1为结尾的字符串t&#xff0c;相同子序列的长度为dp[i][j]。 2.递推公式 if (s[i…

51、全连接 - 特征的全局融合

Resnet50 中的核心算法,除了卷积、池化、bn、relu之外,在最后一层还有一个全连接。 下图是 Resnet50 网络结构结尾的部分,最后一层 Gemm(通用矩阵乘法)实现的就是全连接操作。而矩阵乘法我们之前介绍过,传送门在:矩阵乘。 卷积也好,矩阵乘法也好,其目的都是为了完成神…

RT_Thread 调试笔记

说明&#xff1a;记录日常使用 RT_Thread 开发时做的笔记。 1.打印相关 1.打印宏定义&#xff0c;可以打印打印所在文件&#xff0c;函数&#xff0c;行数。 #define PRINT_TRACE() printf("-------%s:%s:%d------\r\n", __FILE__, __FUNCTION__, __LINE__);2. rt…

阶段十-分布式-任务调度

第一章 定时任务概述 在项目中开发定时任务应该一种比较常见的需求&#xff0c;在 Java 中开发定时任务主要有三种解决方案&#xff1a;一是使用JDK 自带的 Timer&#xff0c;二是使用 Spring Task&#xff0c;三是使用第三方组件 Quartz Timer 是 JDK 自带的定时任务工具,其…

普通用户用哪款电脑杀毒软件最好?

前言 各位小伙伴接触到电脑的时候&#xff0c;都一定有听过“电脑一定要安装杀毒软件”这句话。 毕竟在电脑诞生之初到今天&#xff0c;电脑木马和病毒依旧存在。 中了木马或病毒的电脑会出现什么现象&#xff1f;具体得看中了什么样的病毒。 但轻则资料泄漏、电脑瘫痪&…