当前位置:网站首页>LayaBox---TypeScript---类型兼容性
LayaBox---TypeScript---类型兼容性
2022-07-30 17:38:00 【格拉格拉】
目录
1.基础
TypeScript里的类型兼容性是基于结构子类型的。
结构类型是一种只使用其成员来描述类型的方式。
interface Named {
name: string;
}
class Person {
name: string;
}
let p: Named;
// OK, because of structural typing
p = new Person();
在使用基于名义类型的语言,比如C#或Java中,这段代码会报错,
因为Person类没有明确说明其实现了Named接口。TypeScript的结构性子类型是根据JavaScript代码的典型写法来设计的。 因为JavaScript里广泛地使用匿名对象,例如函数表达式和对象字面量,所以使用结构类型系统来描述这些类型比使用名义类型系统更好。
️注意:关于可靠性的注意事项
TypeScript的类型系统允许某些在编译阶段无法确认其安全性的操作。当一个类型系统具此属性时,被当做是“不可靠”的。TypeScript允许这种不可靠行为的发生是经过仔细考虑的。
2.开始
TypeScript结构化类型系统的基本规则是,如果x要兼容y,那么y至少具有与x相同的属性。
interface Named {
name: string;
}
let x: Named;
// y's inferred type is { name: string; location: string; }
let y = { name: 'Alice', location: 'Seattle' };
x = y;检查函数参数时使用相同的规则:
function greet(n: Named) {
console.log('Hello, ' + n.name);
}
greet(y); // OK️注意,
y有个额外的location属性,但这不会引发错误。 只有目标类型(这里是Named)的成员会被一一检查是否兼容。
这个比较过程是递归进行的,检查每个成员及子成员。
3.比较两个函数
相对来讲,在比较原始类型和对象类型的时候是比较容易理解的,问题是如何判断两个函数是兼容的。
let x = (a: number) => 0;
let y = (b: number, s: string) => 0;
y = x; // OK
x = y; // Error
要查看x是否能赋值给y,首先看它们的参数列表。 x的每个参数必须能在y里找到对应类型的参数。
注意的是参数的名字相同与否无所谓,只看它们的类型。 这里,x的每个参数在y中都能找到对应的参数,
所以允许赋值。
第二个赋值错误,因为y有个必需的第二个参数,但是x并没有,所以不允许赋值。Array#forEach给回调函数传3个参数:数组元素,索引和整个数组。
尽管如此,传入一个只使用第一个参数的回调函数也是很有用的:
let items = [1, 2, 3];
// Don't force these extra arguments
items.forEach((item, index, array) => console.log(item));
// Should be OK!
items.forEach((item) => console.log(item));下面来看如何处理返回值类型,创建两个仅是返回值类型不同的函数:
let x = () => ({name: 'Alice'});
let y = () => ({name: 'Alice', location: 'Seattle'});
x = y; // OK
y = x; // Error, because x() lacks a location property
类型系统强制源函数的返回值类型必须是目标函数返回值类型的子类型。3.1.函数参数双向协变
当比较函数参数类型时,只有当源函数参数能够赋值给目标函数或者反过来时才能赋值成功。 这是不稳定的,因为调用者可能传入了一个具有更精确类型信息的函数,但是调用这个传入的函数的时候却使用了不是那么精确的类型信息。
enum EventType { Mouse, Keyboard }
interface Event { timestamp: number; }
interface MouseEvent extends Event { x: number; y: number }
interface KeyEvent extends Event { keyCode: number }
function listenEvent(eventType: EventType, handler: (n: Event) => void) {
/* ... */
}
// 不健全,但是有用和常见
listenEvent(EventType.Mouse, (e: MouseEvent) => console.log(e.x + ',' + e.y));
// Undesirable alternatives in presence of soundness
listenEvent(EventType.Mouse, (e: Event) => console.log((<MouseEvent>e).x + ',' + (<MouseEvent>e).y));
listenEvent(EventType.Mouse, <(e: Event) => void>((e: MouseEvent) => console.log(e.x + ',' + e.y)));
// Still disallowed (clear error). Type safety enforced for wholly incompatible types
listenEvent(EventType.Mouse, (e: number) => console.log(e));3.2.可选参数及剩余参数
比较函数兼容性的时候,可选参数与必须参数是可互换的。 源类型上有额外的可选参数不是错误,目标类型的可选参数在源类型里没有对应的参数也不是错误。
当一个函数有剩余参数时,它被当做无限个可选参数。
这对于类型系统来说是不稳定的,但从运行时的角度来看,可选参数一般来说是不强制的,因为对于大多数函数来说相当于传递了一些undefinded。
有一个好的例子,常见的函数接收一个回调函数并用对于程序员来说是可预知的参数但对类型系统来说是不确定的参数来调用:
function invokeLater(args: any[], callback: (...args: any[]) => void) {
/* ... Invoke callback with 'args' ... */
}
// Unsound - invokeLater "might" provide any number of arguments
invokeLater([1, 2], (x, y) => console.log(x + ', ' + y));
// Confusing (x and y are actually required) and undiscoverable
invokeLater([1, 2], (x?, y?) => console.log(x + ', ' + y));3.3.函数重载
对于有重载的函数,源函数的每个重载都要在目标函数上找到对应的函数签名。 这确保了目标函数可以在所有源函数可调用的地方调用。
4.枚举
枚举类型与数字类型兼容,并且数字类型与枚举类型兼容。不同枚举类型之间是不兼容的。
enum Status { Ready, Waiting };
enum Color { Red, Blue, Green };
let status = Status.Ready;
status = Color.Green; // Error5.类
类有静态部分和实例部分的类型。 比较两个类类型的对象时,只有实例的成员会被比较。 静态成员和构造函数不在比较的范围内。
class Animal {
feet: number;
constructor(name: string, numFeet: number) { }
}
class Size {
feet: number;
constructor(numFeet: number) { }
}
let a: Animal;
let s: Size;
a = s; // OK
s = a; // OK类的私有成员和受保护成员:
类的私有成员和受保护成员会影响兼容性。 当检查类实例的兼容时,如果目标类型包含一个私有成员,那么源类型必须包含来自同一个类的这个私有成员。 同样地,这条规则也适用于包含受保护成员实例的类型检查。 这允许子类赋值给父类,但是不能赋值给其它有同样类型的类。
6.泛型
因为TypeScript是结构性的类型系统,类型参数只影响使用其做为类型一部分的结果类型。
interface Empty<T> {
}
let x: Empty<number>;
let y: Empty<string>;
x = y; // OK, because y matches structure of x上面代码里,x和y是兼容的,因为它们的结构使用类型参数时并没有什么不同。
interface NotEmpty<T> {
data: T;
}
let x: NotEmpty<number>;
let y: NotEmpty<string>;
x = y; // Error, because x and y are not compatible
在这里,泛型类型在使用时就好比不是一个泛型类型。对于没指定泛型类型的泛型参数时,会把所有泛型参数当成any比较。 然后用结果类型进行比较,就像上面第一个例子。
let identity = function<T>(x: T): T {
// ...
}
let reverse = function<U>(y: U): U {
// ...
}
identity = reverse; // OK, because (x: any) => any matches (y: any) => any7.高级主题
子类型与赋值
目前为止,我们使用了“兼容性”,它在语言规范里没有定义。 在TypeScript里,有两种兼容性:子类型和赋值。 它们的不同点在于,赋值扩展了子类型兼容性,增加了一些规则,允许和any来回赋值,以及enum和对应数字值之间的来回赋值。
语言里的不同地方分别使用了它们之中的机制。 实际上,类型兼容性是由赋值兼容性来控制的,即使在implements和extends语句也不例外。
边栏推荐
- esp32系列(5):esp32 蓝牙架构学习
- C陷阱与缺陷 第6章 预处理器 6.2 宏并不是函数
- 顺通海关查验预约综合管理系统
- 简易的命令行入门教程
- 基于MATLAB的电力系统短路故障分析与仿真
- 论文阅读之《DeepIlluminance: Contextual IlluminanceEstimation via Deep Neural Networks》
- 数据库系统原理与应用教程(069)—— MySQL 练习题:操作题 95-100(十三):分组查询与聚合函数的使用
- FastJson反序列化漏洞(复现)
- JMeter Notes 3 | JMeter Installation and Environment Instructions
- matlab simulink锂离子电池智能充电策略研究
猜你喜欢
![Valid bracketed strings [greedy exercise]](/img/1c/5cefb53bc4aba54dd79b0cc9b09b0d.png)
Valid bracketed strings [greedy exercise]

DLCM - 基于列表上下文信息的重排序模型
![有效的括号字符串[贪心练习]](/img/1c/5cefb53bc4aba54dd79b0cc9b09b0d.png)
有效的括号字符串[贪心练习]

Metaverse Web 3.0 和 DeFi大师班

Moralis去中心化Web3应用开发教程

知识蒸馏3:YOLOV5项目准备

592. Fraction Addition and Subtraction

WeChat applet picker scroll selector use detailed explanation

顺通海关查验预约综合管理系统

一个 15 年 SAP ABAP 开发人员分享的 SAPGUI 一些个性化设置和实用小技巧试读版
随机推荐
How Google earth engine realizes the arrangement and selection of our time list
shell快速移植
论文阅读之《Color Constancy Using CNNs》
想要写出好的测试用例,先要学会测试设计
顺通海关查验预约综合管理系统
Microsoft Office 2019 软件下载安装详细教程!
Metaverse Web 3.0 和 DeFi大师班
FastJson反序列化漏洞(复现)
JMeter Notes 3 | JMeter Installation and Environment Instructions
un7.30:linux——如何在docker容器中安装MySQL?
Express framework connects MySQL and ORM framework
宝塔搭建PHP自适应懒人网址导航源码实测
Error EPERM operation not permitted, mkdir ‘Dsoftwarenodejsnode_cache_cacach两种解决办法
什么是无损检测设备?
阿里SIM-基于检索的用户行为兴趣CTR模型(Search-based user Interest Model(SIM))
数据库系统原理与应用教程(069)—— MySQL 练习题:操作题 95-100(十三):分组查询与聚合函数的使用
自动化早已不是那个自动化了,谈一谈自动化测试现状和自我感受……
SYSCALL SWAPGS
Summary of String Copy, Concatenation, Comparison and Split Functions (1)
esp32系列(5):esp32 蓝牙架构学习