TS:子类型关系
子类型关系
- 1、概念
- 1.1 里氏替换原则
- 1.2 自反性
- 1.3 传递性
- 2、顶端类型 和 尾端类型
- 3、字面量类型
- 4、undefined 和 null
- 5、枚举类型
- 6、函数类型
- 6.1 变型
- 6.1.1 协变
- 6.1.2 逆变
- 6.1.3 双变
- 6.2 函数类型间的子类型关系
- 6.2.1 函数参数数量
- 6.2.2 函数参数类型
- A、非严格函数类型检查
- B、严格函数类型检查
- 6.2.3 函数返回值类型
- 6.2.4 函数重载
- 7、对象类型
- 7.1 属性成员类型
- 7.2 调用签名 和 构造签名
- 7.3 字符串索引签名 和 数值型索引签名
- 8、类类型
- 9、泛型类型
- 9.1 泛型对象类型
- 9.2 泛型函数类型
- 9.2.1 非严格泛型函数类型检查
- 9.2.2 严格泛型函数类型检查
- 10、联合类型 和 交叉类型
- 10.1 联合类型
- 10.2 交叉类型
1、概念
1.1 里氏替换原则
程序中任何使用了超类型 的地方都可以用其 子类型 进行替换,并且在替换后程序的行为保持不变。
1.2 自反性
任意类型都是其 自身 的子类型和超类型。
1.3 传递性
若 类型A 是 类型B 的子类型,且 类型B 是 类型C 的子类型,那么 类型A 也是 类型C 的子类型。
2、顶端类型 和 尾端类型
顶端类型是一种通用超类型,所有类型都是顶端类型的子类型;同时,尾端类型是所有类型的子类型。
TS 中存在两种顶端类型,即any类型和unknown类型。因此,所有类型都是any类型和unknown类型的子类型。
3、字面量类型
字面量类型是其对应的基础原始类型的子类型。
例如:maintainer 类型是 name 类型的子类型
type maintainer = 'Bob';
type name = 'string';
4、undefined 和 null
Undefined类型是 除尾端类型 never 外 所有类型的子类型,其中也包括null类型。
Null类型是 除尾端类型和undefined类型外 的所有类型的子类型。
5、枚举类型
在联合枚举类型中,每个枚举成员都能够表示一种类型,同时联合枚举成员类型是联合枚举类型的子类型。
什么是联合枚举类型?
枚举成员类型都是字面量类型的枚举类型。
6、函数类型
函数类型由 参数类型 和 返回值类型 构成。在比较两个函数类型间的子类型关系时要同时考虑 参数类型 和 返回值类型。
6.1 变型
在学习函数类型的字类型和超类型之间的关系前,我们要先了解一个和函数类型关系非常紧密的概念——变型。
所谓变型就是描述的是复杂类型的组成类型是如何影响复杂类型间的子类型关系的。
现约定如果复杂类型 Complex 是由 类型T 构成,那么我们将其记作 Complex(T)。
6.1.1 协变
假设有两个复杂类型 Complex(A) 和 Complex(B) ,如果由A是B的子类型能够得出 Complex(A) 是 Complex(B) 的子类型,那么我们将这种变型称作协变。
协变关系维持了复杂类型与其组成类型间的子类型关系。
6.1.2 逆变
如果由A是B的子类型能够得出 Complex(B) 是 Complex(A) 的子类型,那么我们将这种变型称作逆变。
6.1.3 双变
如果由 A 是 B 的子类型或者 B 是 A 的子类型能够得出 Complex(A) 是 Complex(B) 的子类型,那么我们将这种变型称作双变。
双变同时具有协变关系与逆变关系。
6.2 函数类型间的子类型关系
6.2.1 函数参数数量
子类型的 必选参数 的个数 不能多于 父类型 中的参数个数。
若函数类型 S 是函数类型 T 的子类型,则 S 中的每一个必选参数必须能够在T中找到对应的参数。
当T中存在 可选参数 或 剩余参数 时,函数类型检查是不可靠的。因为当使用子类型 S 替换了超类型 T 之后,调用 S 时的实际参数个数可能少于必选参数的个数。例如,有如下的函数s 和函数t ,其中 s 是 t 的子类型,使用一个实际参数调用函数 t 没有问题,但是将 t 替换为其子类型 s 后会产生错误,因为调用 s 需要两个实际参数。
function s(a: number, b: number): void {}
function t(...x:number[]): void {}t(0);
s(0); // 编译错误
6.2.2 函数参数类型
函数的参数类型会影响函数类型间的子类型关系。
A、非严格函数类型检查
在该模式下,函数参数类型与函数类型是 双变 关系。
若函数类型 S 是函数类型 T 的子类型,那么 S 的参数类型必须是 T 中对应参数类型的【子类型】或者【超类型】。这意味着在对应位置上的两个参数只要存在子类型关系即可,而不强调哪一方应该是另一方的子类型。
type S = (a: 0 | 1) => void;
type T = (x: number) => void;
此例中,S 是 T 的子类型,同时 T 也是 S 的子类型。
B、严格函数类型检查
strictFunctionTypes 编译选项用来启用严格的函数类型检查。
在该模式下,函数参数类型与函数类型是 逆变 关系,而非相对宽松的双变关系。
若函数类型 S 是函数类型 T 的子类型,那么 S 的参数类型必须是 T 中对应参数类型的 超类型。
6.2.3 函数返回值类型
在确定函数类型间的子类型关系时,编译器将检查函数返回值类型 是否兼容 。
不论是否启用了strictFunctionTypes 编译选项,函数返回值类型与函数类型始终是 协变 关系。
若函数类型 S 是函数类型 T 的子类型,那么 S 的返回值类型必须是 T 的返回值类型的 子类型。
我理解,无论是函数返回值类型还是严格模式下的函数参数类型检查,都要满足赋值兼容性,才符合里氏替换原则。
对于严格模式下的参数类型,超类型函数的实参要能赋值给子类型的形参。
对于函数返回值类型,子类型函数的返回值要能赋值给超类型函数的返回值。
6.2.4 函数重载
在确定函数类型间的子类型关系时,编译器将检查函数重载签名类型是否兼容。
若函数类型 S 是函数类型 T 的子类型,并且 T 存在函数重载,那么 T 的每一个函数重载必须能够在 S 的函数重载中找到与其对应的子类型。
7、对象类型
在比较对象类型的子类型关系时要分别考虑 每一个 类型成员。
在结构化子类型系统中仅通过比较两个对象类型的 类型成员列表 就能够确定它们的子类型关系。对象类型的名称完全不影响对象类型间的子类型关系。
例如,以下示例中 类型 A 和 类型 B 是相同类型,类型 C 是 类型 A 和 类型 B 的超类型。
type A = {name: string,age: number
}
type B = {name: string,age: number
}
type C = {name: string
}
对象类型的子类型关系要满足以下条件:
- 在数量上,超类型对象类型的成员数量不能多于 子类型对象类型的成员数量。
- 在属性成员的可访问性上,超类型中的必选属性在子类型中也必须是必选属性。
- 在成员类型上,子类型的成员类型是超类型中对应的成员类型的子类型。
7.1 属性成员类型
超类型的每个属性成员 M 都能够在子类型中找到同名属性成员 N,且 N 是 M 的子类型。
7.2 调用签名 和 构造签名
超类型中的调用签名 M 都能够在子类型中找到对应的调用签名 N,且 N 是 M 的子类型。
对象类型中的构造签名与调用签名有着相同的判断规则。
7.3 字符串索引签名 和 数值型索引签名
父类型中有索引签名,子类型中也要有,并子类型的索引签名类型是父类型索引签名类型的子类型。
8、类类型
在确定两个类类型之间的子类型关系时,仅检查类的 实例成员 类型,类的 静态成员类型 以及 构造函数类型 不进行检查。
如果类中存在 私有成员 或 受保护成员,那么在确定类类型间的子类型关系时要求私有成员和受保护成员 来自同一个类,这意味着两个类需要存在 继承关系。
例如,以下代码中,Point 和 Position 中的受保护成员 x 都来自Point,因此 Position 是 Point 的子类型。
class Point {protected x: number = 0;
}
class position extends Point {protected y: number = 0;
}
9、泛型类型
9.1 泛型对象类型
对于泛型接口、泛型类和表示对象类型的泛型类型别名而言,实例化泛型类型时使用的实际类型参数 不影响 子类型关系,真正影响子类型关系的是泛型实例化后的 结果对象类型。
9.2 泛型函数类型
TS编译器提供了noStrictGenericChecks 编译选项用来启用或关闭严格泛型函数类型检查。
9.2.1 非严格泛型函数类型检查
编译器先将所有的泛型类型参数替换为 any 类型,然后再确定子类型关系。这意味着泛型类型参数不影响泛型函数的子类型关系。
type A = <T, U>(x: T, y: U) => [T, U];
type B = <S>(x: S, y: S) => [S, S];
将所有的类型参数替换为any类型,结果如下:
type A = (x: any, y: any) => [any, any];
type B = (x: any, y: any) => [any, any];
9.2.2 严格泛型函数类型检查
先通过类型推断来 统一 两个泛型函数的类型参数,然后再确定两者的子类型关系。
type A = <T, U>(x: T, y: U) => [T, U];
type B = <S>(x: S, y: S) => [S, S];
如果我们想要确定 A 是否为 B 的子类型,那么先尝试使用 B 的类型来推断A的类型。通过比较每个参数类型和返回值类型,能够得出类型参数 T 和 U 均为 S。接下来使用推断的结果来实例化 A 类型,即将类型 A 中的 T 和 U 均替换为 S,替换后的结果如下:
type A = <S>(x: S, y: S) => [S, S];
type B = <S>(x: S, y: S) => [S, S];
在统一了类型参数之后,再来比较泛型函数间的子类型关系。因为统一后的类型 A 和 B 相同,所以 A 是 B 的子类型。
如果我们最开始想要确定 B 是否为 A 的子类型,那么这时将由 A 向 B 来推断并统一类型参数的值。经推断,S 的类型为联合类型“T | U”,然后使用“S = T | U”来实例化 B 类型,结果如下:
type A = <T, U>(x: T, y: U) => [T, U];
type B = <T, U>(x: T | U, y: T | U) => [T | U, T | U];
此时,B 不是 A 的子类型,因为 B 的返回值类型不是 A 的返回值类型的子类型。
10、联合类型 和 交叉类型
10.1 联合类型
联合类型由若干成员类型构成,在计算联合类型的子类型关系时需要考虑每一个成员类型。
假设有联合类型 S = S0 | S1 和任意类型 T,如果成员类型 S0 是类型 T 的子类型,并且成员类型 S1 是类型 T 的子类型,那么联合类型 S 是类型 T 的子类型。例如,有如下定义的联合类型 S 和类型 T 。
type S = 0 | 1;
type T = number;
此例中,联合类型 S 是类型 T 的子类型。
假设有联合类型 S = S0 | S1 和任意类型 T,如果类型 T 是成员类型 S0 的子类型,或者类型T是成员类型 S1 的子类型,那么类型 T 是联合类型 S 的子类型。例如,有如下定义的联合类型 S 和类型 T :
type S = number | string;
type T = 0;
此例中,类型T是联合类型S的子类型。
10.2 交叉类型
交叉类型由若干成员类型构成,在计算交叉类型的子类型关系时需要考虑每一个成员类型。
假设有交叉类型 S = S0 & S1 和任意类型 T,如果成员类型 S0 是类型 T 的子类型,或者成员类型 S1 是类型 T 的子类型,那么交叉类型 S 是类型 T 的子类型。
type S = { x: number } & { y: number };
type T = { x: number };
假设有交叉类型 S = S0 & S1 和任意类型 T,如果类型 T 是成员类型 S0 的子类型,并且类型 T 是成员类型 S1 的子类型,那么类型 T 是交叉类型 S 的子类型。
type S = { x: number } & { y: number };
type T = { x: number; y: number; z: number };
相关文章:
TS:子类型关系
子类型关系 1、概念1.1 里氏替换原则1.2 自反性1.3 传递性 2、顶端类型 和 尾端类型3、字面量类型4、undefined 和 null5、枚举类型6、函数类型6.1 变型6.1.1 协变6.1.2 逆变6.1.3 双变 6.2 函数类型间的子类型关系6.2.1 函数参数数量6.2.2 函数参数类型A、非严格函数类型检查B…...
IDEA插件(MyBatis Log Free)
引言 在Java开发中,MyBatis 是一款广泛使用的持久层框架,它简化了SQL映射并提供了强大的数据访问能力。为了更好地调试和优化MyBatis应用中的SQL语句执行,一款名为 MyBatis Log Free 的 IntelliJ IDEA 插件应运而生。这款插件旨在帮助开发者…...
Redis(八)哨兵机制(sentinel)
文章目录 哨兵机制案例认识异常 哨兵运行流程及选举原理主观下线(Subjectively Down)ODown客观下线(Objectively Down)选举出领导者哨兵选出新master过程 哨兵使用建议 哨兵机制 吹哨人巡查监控后台master主机是否故障,如果故障了根据投票数自动将某一个从库转换为新…...
[数据结构]-哈希
前言 作者:小蜗牛向前冲 名言:我可以接受失败,但我不能接受放弃 如果觉的博主的文章还不错的话,还请点赞,收藏,关注👀支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 本期学习目标&…...
宝塔控制面板配置SSL证书实现网站HTTPS
宝塔安装SSL证书提前申请好SSL证书,如果还没有,先去Gworg里面申请,一般几分钟就可以下来,申请地址:首页-Gworg官方店-淘宝网 一、登录邮箱下载:Gworg证书文件目录 ,都会有以下五个文件夹。宝塔…...
elasticsearch优化总结
参考: https://docs.docker.com/manuals/ Manuals | Docker Docs Run Elasticsearch locally | Elasticsearch Guide [8.12] | Elastic 让你的ES查询性能起飞:Elasticsearch 查询优化攻略“一网打尽” - 知乎...
图论第三天|127. 单词接龙 841.钥匙和房间 463. 岛屿的周长 1971. 寻找图中是否存在路径 684.冗余连接 685.冗余连接II
目录 Leetcode127. 单词接龙Leetcode841.钥匙和房间Leetcode463. 岛屿的周长Leetcode1971. 寻找图中是否存在路径Leetcode684.冗余连接Leetcode685.冗余连接II Leetcode127. 单词接龙 文章链接:代码随想录 题目链接:127. 单词接龙 思路:广搜搜…...
react的高阶函数HOC:
React 的高阶组件(Higher-Order Component,HOC)是一种用于复用组件逻辑的模式。它是一个函数,接收一个组件作为参数,并返回一个新的增强过的组件。 HOC 可以用于实现以下功能: 代码复用:通过将…...
STM32——中断系统和外部中断EXTI
一、中断 1.1中断系统 中断系统是管理和执行中断的逻辑结构; 1.2中断 系统在执行主程序过程中,出现了特定的触发条件(触发源),系统停止执行当前程序,转而去执行中断程序,执行完毕后…...
使用uniApp+vue3+Vite4+pinia+sass技术栈构建微信小程序
使用uniApp的cli模式安装,可以使用vscode开发。不用再单独去下载HBuilderX. 1.基础安装 vue3tsuniapp 方法一: npx degit dcloudio/uni-preset-vue#vite-ts my-vue3-project方法二:可以去uni-preset-vue的vite分支下选择vite-ts直接下载zi…...
npm 被滥用 -- 有人上传了 700 多个武林外传切片视频
Sonatype 安全研究团队最近曝光了一起滥用 npm 的案例 —— 他们发现在 npm 上托管的 748 个软件包实际上是视频文件。 据介绍,这些软件包每个大小约为 54.5MB,包名以 “wlwz” 为前缀,并附带了代表日期的数字。根据时间戳显示,这…...
代码随想录算法训练营29期|day34 任务以及具体任务
第八章 贪心算法 part03 1005.K次取反后最大化的数组和 class Solution {public int largestSumAfterKNegations(int[] nums, int K) {// 将数组按照绝对值大小从大到小排序,注意要按照绝对值的大小nums IntStream.of(nums).boxed().sorted((o1, o2) -> Math.ab…...
LeetCode 每日一题 2024/1/22-2024/1/28
记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步 目录 1/22 670. 最大交换1/23 2765. 最长交替子数组1/24 2865. 美丽塔 I1/25 2859. 计算 K 置位下标对应元素的和1/26 2846. 边权重均等查询1/27 2861. 最大合金数1/28 365. 水壶…...
好用的学习与开发工具
1. 首推 UTools 官网地址 uTools官网 - 新一代效率工具平台 介绍 uTools 是一个极简、插件化的现代桌面软件,通过自由选配丰富的插件,打造得心应手的工具集合。 通过快捷键(默认 alt space )就可以快速呼出这个搜索框。你可…...
(自用)learnOpenGL学习总结-高级OpenGL-立方体贴图
ok终于来到了立方体贴图了,在这里面我们可以加入好看的天空包围盒,这样的画我们的背景就不再是黑色的了! 首先,立方体贴图和前面的sampler2D贴图一样,不过是6个2D组成的立方体而已。 那么为什么要把6个组合在一起呢&…...
【计算机网络】——TCP协议
📑前言 本文主要是【计算机网络】——传输层TCP协议的文章,如果有什么需要改进的地方还请大佬指出⛺️ 🎬作者简介:大家好,我是青衿🥇 ☁️博客首页:CSDN主页放风讲故事 🌄每日一句…...
sql优化的方法
目录 一、准备数据 1.1、创建表结构 1.2、创建存储过程 二、索引介绍 2.1、类型介绍 2.2、建立索引 2.3、建立复合索引 2.4、查看所有建立的索引 2.5、删除索引 三、EXPLAIN分析参数说明 四、SQL优化案例 4.1、避免使用SELECT * 4.2、慎用UNION关键字 4.4、避免使…...
C++ Qt开发:运用QJSON模块解析数据
Qt 是一个跨平台C图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍如何运用QJson组件的实现对JSON文本的灵活解析…...
MySQL数据库基础合集
MySQL数据库基础合集 目录 MySQL数据库基础合集SQL关键字DDL关键字DML关键字DQL关键字DCL关键字约束关键字 SQL基础数据类型整数类型字符类型浮点类型时间类型 数据定义语言DDL1.查看数据库2.创建库3.删除库4.切换库5.创建表6.删除表7.查看表8.查看表属性9.插入列10.修改列11.设…...
oracle19.22的patch已发布
2024年01月16日,oracle发布了19.22的patch 具体patch如下 Reserved for Database - Do not edit or delete (Doc ID 19202401.9) 文档ID规则如下 19(版本)年份(202x)(季度首月01,04,07,10).9 往期patch no信息和下…...
接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...
