【TypeScript】类型兼容性与相关类型讲解

news2025/1/18 11:47:44

目录

类型兼容性

对象类型兼容性

接口类型兼容性

函数类型兼容性

索引签名类型

映射类型

索引查询类型

交叉类型


类型兼容性

在TS中,类型采用的是结构化类型系统,也叫做 duck typing(鸭子类型),类型检查关注的是值所具有的形状。也就是说,在结构化系统中,如果两个对象具有相同形状,则认为他们属于同一类型。

class obj {x: number; y: number}
class obj1 {x: number; y: number}
// 因为TS的结构化类型,只检查obj与obj1的结构是否相同
const p: obj = new obj1()

注意:如果在 Nominal Type System中(比如:C#、java等),它们是不同的类,类型无法兼容。

对象类型兼容性

在结构化系统中,如果两个对象具有相同的形状,则认为他们属于同一类型。这种条件成立的前提在于成员多的可以赋予成员少的,反之则报错。如下:

class obj {x: number; y: number}
class obj1 {x: number; y: number; z: number}

// 成员多的 obj1 可以赋值给成员少的 obj
const p: obj = new obj1()

// const p1: obj1 = new obj() 成员少不能赋值给成员多的,报错

接口类型兼容性

接口类型兼容性,类似于class。并且class和interface之间也可以兼容。

interface person {
  name: string
  age: number
}
interface person1 {
  name: string
  age: number
}
interface person2 {
  name: string
  age: number
  say: ()=> void
}
let p1: person = {name:'张三',age:18}
let p2: person1 = {name:'李四',age:17}
let p3: person2 = {name:'王五',age:16,say(){}}
p2=p1
p1=p2
// p3=p1 报错

// 类和接口之间也可以兼容
class person3 {
  name: string
  age: number
  say: ()=> void
}
let p4: person3 = {name:'陈六',age:15,say(){}}
p2=p4

函数类型兼容性

函数类型的兼容性比较复杂,需要考虑以下三种情况:

参数个数:参数多的兼容参数少的,即参数少的可以赋值给参数多的。

type F1 = (a: number) => void
type F2 = (a: number,b: number) => void
let f1: F1 = (a=1)=>{}
let f2: F2
f2=f1
// f1=f2 参数多的不能赋值给参数少的 报错

参数类型:相同位置的参数类型要相同(原始类型)或兼容(对象类型)。

type F1 = (a: number) => void
type F2 = (a: number) => void
let f1: F1 = ()=>{}
let f2: F2 = ()=>{}
f1 = f2

在对象类型中,参数可能很多,这个时候就需要参数多的兼容参数少的,即参数少的能赋值给参数多的,如下:

interface point1 {
  name:string
  age:number
}
interface point2 {
  name:string
  age:number
  say():void
}
type F1 = (P:point1) => void // 相当于两个参数
type F2 = (P:point2) => void // 相当于三个参数

let f1:F1=()=>{}
let f2:F2
f2=f1

返回值类型:只关注返回值类型本身即可。如果返回值类型是原始类型,类型之间要相同;如果返回值类型是对象类型,成员多的可以赋值给成员少的。

// 原始类型
type F1 = ()=> string
type F2 = ()=> string
let f1: F1 = ()=>{return '1'}
let f2: F2 = f1

// 对象类型
type F3 = {name:string}
type F4 = {name:string,age:number}
let f3: F3
let f4: F4 = {name:'张三',age:18}
f3=f4

索引签名类型

绝大部分情况下,我们可以在使用对象前就确定对象的结构,并为对象添加准确的类型。然而当无法确定对象中有哪些属性(或者说对象中可以出现任意多个属性),此时就需要用到索引签名类型。

interface anyObj {
  // 使用 [key: string] 来约束该接口允许出现的属性名称。
  // key只是一个占位符,可以换成任意合法的名称
  [key: string]: number
}
let obj: anyObj = {
  // 表示只要是string类型都可以出现在对象中,这样对象就可以出现任意多个字符
  a:1,
  abc:12,
  xzx:1
}

在JS中数组是一类特殊的对象,特殊在数组的键也就是索引是数组类型,并且数组也可以出现任意多个元素。所以在数组对应的泛型接口中,也用到了索引签名类型。

interface MyArr<type>{
  [index: number]: type
}
// 符合数组索引必须是 number 这一类型。
let arr: MyArr<number> = [1,2,3]
arr[0]

映射类型

映射类型是基于旧类型创建新类型(对象类型),减少重复、提升开发效率。映射类型是基于索引签名类型的,所以该语法类似于索引签名类型,也使用了 [] 。

注意:映射类型只能在类型别名中使用,不能在接口中使用。

// 普通写法:每次写一个变量就要再一次声明其类型
type Type1 = {x:number;y:number;z:number}
// 映射写法:创建对象的新类型与声明的类型结构完全一致。
type PropKeys = 'x'|'y'|'z'
type Type2 = {[keys in PropKeys]: number}

映射类型除了上文的联合类型创建新类型外,还可以根据对象类型来创建

type props = {a: number;b: string;c: boolean}
// keyof表示键名是props中所有键名的任意一个。
// 这种方式类似将许多类型统一为同一个类型。
type Type = {[key in keyof props]: number}

索引查询类型

索引查询类型作用是用来查询属性的类型。注意:[]中的属性必须存在于被查询类型中,否则会报错。如下:

type props = {a: number;b: string;c: boolean} 
// 查询单个索引类型
type Type = props['a']
// 查询多个索引类型
type Type1 = props['a'|'b']
// 查询所有索引类型
type Type2 = props[keyof props]

交叉类型

交叉类型(&):功能类似于接口继承(extends),用于组合多个类型为一个类型(常用于对象类型),使用教程类型后,新的类型就具备被交叉的类型的所有属性类型。如下:

interface Cat {
  name:string
}
interface Dog {
  say():void
}
// Animals属性同时具备 接口 Cat和Dog 的所有属性
type Animals = Cat & Dog
let p: Animals = {
  name:'毛',
  say(){
    console.log('汪汪');
  }
}

交叉类型(&)与 接口继承(extends)的对比:

相同点:都可以实现对象类型的组合。

不同点:两种方式实现类型组合时,对于同名属性之间,处理类型冲突的方式不同。

当不同的接口类型出现同名属性不兼容的时候,接口继承处理的方法是报错

 interface Cat {
  fn:(value:number)=>string
 }
 interface Dog extends Cat {
  fn:(value:string)=>string
 }

当不同的接口类型出现同名属性不兼容的时候,交叉类型处理的方法是处理成联合类型

interface Cat {
fn:(value:number)=>string
}
interface Dog {
fn:(value:string)=>string
}
type Animals = Cat & Dog
// 交叉类型将fn的参数值类型变为联合类型  fn:(value:number|string) => string
// ! 作用强调这个值不为空
let p!: Animals
// 没有报错
p.fn(1) 
p.fn('2')

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电脑c盘备份怎么操作?备份C盘的6个步骤

电脑出现问题&#xff0c;想要修复又不知该怎么操作。可能你会想要重装电脑的系统&#xff0c;但是在操作之前&#xff0c;一定要对电脑重要的数据做好备份。尤其是电脑C盘里面存储着我们很多重要的数据&#xff0c;电脑c盘备份怎么进行&#xff1f;跟着下面6个操作步骤进行&am…

<Linux线程池、线程安全(单例模式、STL、智能指针)、读者写者问题及线程扩展与总结>——《Linux》

目录 1.线程池 1.1 线程池: 1.2 线程池的应用场景&#xff1a; 1.3 线程池的种类&#xff1a; 1.4 线程池示例&#xff1a; 1.5 线程池编程模拟实现&#xff1a; 2. 线程安全的单例模式 2.1 什么是单例模式 2.2 什么是设计模式 2.3 单例模式的特点 2.3.1 饿汉实现方…

驱动相关基础

1.程序分类 1.1 裸机程序&#xff1a;直接运行在对应硬件的的程序 1.2 应用程序&#xff1a;只能运行在对应操作系统上的程序 2. 计算机系统的层次结构 2.1 无操作系统的简单的两层结构 2.2 有操作系统的四层层次结构 3. 操作系统 狭义&#xff1a;给应用程序提供运行环…

Python图像处理【7】采样、卷积与离散傅里叶变换

采样、卷积与离散傅里叶变换0. 前言1. 图像傅里叶变换1.1 傅里叶变换基础1.2 傅里叶变换应用1.3 逆傅里叶变换应用2. 利用采样改变图像分辨率2.1 上采样2.2 下采样小结系列链接0. 前言 采样 (Sampling) 是用于选择/丢弃图像像素的空间操作&#xff0c;通常用于增加/减小图像大…

(byte)1658385462>>16=-40,怎么算的?

正文 在 Github 项目mongo-java-driver有一个类ObjectId.java&#xff0c;它的作用是生成唯一 id 的&#xff0c;它的核心实现是下面这样一段代码 [1]&#xff1a; public void putToByteBuffer(final ByteBuffer buffer) {notNull("buffer", buffer);isTrueArgume…

【数据结构Java版】树与二叉树的相关知识全解

目录 一、树型结构 &#xff08;1&#xff09;树的定义 &#xff08;2&#xff09;树的基本术语 &#xff08;3&#xff09;树的存储结构 二、二叉树 &#xff08;1&#xff09;二叉树的定义 &#xff08;2&#xff09;两种特殊二叉树 1.满二叉树 2.完全二叉树 &…

CSS中你可能不知道的Selectors特性

CSS中你可能不知道的Selectors特性本文作者为奇舞团前端开发工程师引言最近看了2022年全球CSS调查报告&#xff0c;发现了一些不常见的伪类和伪元素。伪类:has()html<div><h1>H1</h1><h2>H2</h2><p>h1{margin: 0 0 0.25rem 0}</p> &…

设置访问SSH为密钥访问

1.制作密钥对 ssh-keygen输入会问两个问题 设置公私钥名称&#xff08;可以留白&#xff0c;直接回车&#xff09;设置公私钥密码&#xff08;可以留白&#xff0c;直接回车&#xff09; 第一次输入第二次确认 留空确认的话&#xff0c;生成公私钥。共有两个文件 # 私钥 id…

Rxjava源码分析实践(三)【RxJava基本原理分析之订阅流】

本节,我们从Rxjava使用代码入手,去结合自己已有的知识体系,加查阅部分源码验证的方式,来一起探索一下Rxjava实现的基本原理。 为了本文原理分析环节,可以被更多的人理解、学习,所以小编从初学者的角度,从使用入手,一点点的分析了其中的源码细节、思想,建议大家随着本文…

NCMMSC论文介绍 | 探索语音自监督模型的高效融合算法

本文介绍了清华大学语音与音频技术实验室&#xff08;SATLab&#xff09;与上海交通大学跨媒体语言智能实验室&#xff08;X-LANCE&#xff09;合作的NCMMSC录用论文&#xff1a;Exploring Effective Fusion Algorithms for Speech Based Self-Supervised Learning Models。该论…

动态列合并更新

【问题】 I have one query, would be great if anyone can help me out on this. In SQL, I have two tables with same column names. Want to query if there is any difference in the column values and if yes will update the values(in the first table) else if the…

【工具类】后台Mock工具类

目录一、介绍二、使用方法1. Controller层定义接口2. 编写json文件3. 开启AOP4. 调用接口验证三、源码一、介绍 Controller层定义完接口后&#xff0c;不需要写业务逻辑。编写Json文件&#xff0c;调用接口时返回json文件的数据。 优点&#xff1a; 设计阶段即可定义好接口&…

Centos 图形化yum管理工具 - yum Extender

文章目录背景安装开启yum-GUI工具 - yumexyum list installed列出软件包的依赖yum cleam背景 作为一个yum工程师&#xff0c;长期备受yum 命令的煎熬。 难道yum就乜有一个GUI管理界面吗&#xff1f; yum Extender (简称 yumex ) , 是 yum 的图形化操作界面。可以通过 yumex 方…

ActiveMQ高级特性和大厂面试常考重点

目录 一、引入消息队列之后该如何保证其高可用性 二、异步投递Async Sends 三、延迟投递和定时投递 四、ActiveMQ消费重试机制 五、死信队列 六、如何保证消息不被重复消费呢?幂等性问题你谈谈 一、引入消息队列之后该如何保证其高可用性 ActiveMQ集群模式_zoeil的博客-…

【机器学习】KNN 算法介绍

文章目录一、KNN 简介二、KNN 核心思想实例分析&#xff1a;K 值的影响三、KNN 的关键1. 距离计算1. 闵可夫斯基距离2. 曼哈顿距离3. 欧氏距离4. 切比雪夫距离5. 余弦距离总结2. K值选择四、KNN 的改进&#xff1a;KDTree五、KNN 回归算法参考链接一、KNN 简介 KNN 算法&#…

想在微信上使用chatGPT?小程序?公众号?企业微信,最终还是选择了企业微信版本的chatgpt

chatgpt的接口现在都可以正常用了&#xff0c;但是怎么把这个功能放在手机上随用随开呢&#xff1f;微信个人聊天版本小程序版本公众号版本企业微信版本逻辑实现方式微信个人聊天版本 网上很多微信机器人版本的&#xff0c;但是原理是网页版微信&#xff0c;很多账号都不能登陆…

golang指针

指针 区别于C/C中的指针&#xff0c;Go语言中的指针不能进行偏移和运算&#xff0c;是安全指针。 要搞明白Go语言中的指针需要先知道3个概念&#xff1a;指针地址、指针类型和指针取值。 1.1. Go语言中的指针 Go语言中的函数传参都是值拷贝&#xff0c;当我们想要修改某个变…

Linux中如何理解线程?线程ID到底是什么?

朋友们好&#xff0c;这里简要介绍了进程和线程的区别以及对LINUX中线程ID的理解&#xff0c;本人目前理解尚浅&#xff0c;若文中有表述不当的地方还望理解并指正&#xff0c;谢谢大家&#xff01; 文章目录一&#xff1a;进程和线程二&#xff1a;线程ID和进程地址空间布局一…

5 项目部署

5.1 Linux-项目部署 5.1.1 环境 5.1.1.1 开发环境&#xff08;dev&#xff09; 外部用户无法访问&#xff0c;开发人员使用&#xff0c;版本变动很大 平时大家大多是在Windows或者Mac操作系统下去编写代码进行开发. 在开发环境中安装大量的软件&#xff0c;这样会导致环境的稳…

2022 年度盘点 | 更成熟的 AI,更破圈的技术狂欢

By 超神经内容一览&#xff1a;2022 年 AI 领域发展不断提速&#xff0c;新技术成果纷纷落地&#xff0c;模型迭代加速升级。本文总结了 2022 年 AI 领域各大公司的技术成就。关键词&#xff1a;年终盘点 大厂 技术创新2022 年在此起彼伏的咳嗽声中接近尾声&#xff0c;这一…