21

从两个角度理解 TypeScript 中的类型是什么

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzI3NzIzMDY0NA%3D%3D&%3Bmid=2247488232&%3Bidx=1&%3Bsn=fea878b777624f8289ada0c09ba43c91
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

每日前端夜话 第290篇

翻译: 疯狂的技术宅

作者:Dr. Axel Rauschmayer

来源:2ality.com

正文共:1537  字

预计阅读时间:7 分钟

QbMv63F.png!web

TypeScript中的类型是什么?本文中描述了两种有助于理解它们的观点。

每个角度三个问题

以下三个问题对于理解类型如何工作非常重要,并且需要从两个角度分别回答。

  1. myVariable 具有 MyType 类型是什么意思?

1   let myVariable: MyType = /*...*/;
  1. SourceType 是否可以分配给 TargetType

1   let source: SourceType = /*...*/;
2   let target: TargetType = source;
  1. TypeUnion 是如何从 Type1Type2Type3 派生的?

1   type TypeUnion = Type1 | Type2 | Type3;

观点1:类型是值的集合

从这个角度来看,类型是一组值:

  1. 如果 myVariable 的类型为 MyType ,则意味着所有可以分配给 myVariable 的值都必须是 MyType 集合的元素。

  2. SourceType 可分配给 TargetTypeSourceTypeTargetType 的子集。结果所有能被 SourceType 接受的值也被 TargetType 接受。

  3. 类型 Type1Type2Type3 的类型联合是定义它们集合的集合理论 union。

观点2:类型兼容性关系

从这个角度来看,我们不关心值本身以及在执行代码时它们是如何流动的。相反,我们采取了更加静态的观点:

  • 源代码中包含 location,每个 location 都有一个静态类型。在支持 TypeScript 的编辑器中,如果将光标悬停在 location 上方,则可以看到该 location 的静态类型。

  • 当源 location 通过分配、函数调用等连接到目标 location 时,则源 location 的类型必须与目标 location 的类型兼容。TypeScript 规范通过所谓的 类型关系 (https://github.com/microsoft/TypeScript/blob/master/doc/spec.md#3.11)定义类型兼容性。

  • 类型关系 分配兼容性 (https://github.com/microsoft/TypeScript/blob/master/doc/spec.md#3114-assignment-compatibility)定义什么时候把源类型 S 分配给目标类型 T

  • ST 是相同的类型。

  • STany 类型。

让我们考虑以下问题:

  1. 如果将 myVariable 的静态类型分配给 MyType ,则 myVariable 的类型为 MyType

  2. 如果 SourceType 是兼容分配的,则可以将它们分配给 TargetType

  3. 通过类型关系 apparent 成员 (https://github.com/microsoft/TypeScript/blob/master/doc/spec.md#3111-apparent-members)定义类型 union 的工作方式。

TypeScript 类型系统的一个有趣特征是,同一变量在不同位置可以具有不同的静态类型:

 1const arr = [];
 2// %inferred-type: any[]
 3arr;
 4
 5arr.push(123);
 6// %inferred-type: number[]
 7arr;
 8
 9arr.push('abc');
10// %inferred-type: (string | number)[]
11arr;

名义类型系统与结构类型系统

静态类型系统的职责之一是确定两种静态类型是否兼容:

  • 实际参数的静态类型 U (例如,通过函数调用提供)

  • 对应形式参数的静态类型 T (在函数定义中指定)

这通常意味着检查 U 是否为 T 的子类型。大致有两种检查方法:

  • 名义 类型系统中,两个静态类型如果具有相同的标识(“名称”)则相等。如果明确声明了它们的子类型关系,则一种类型是另一种类型的子类型。

  • 名义类型的语言为 C ++、Java、C#、Swift 和 Rust。

  • 结构 类型系统中,两个静态类型具有相同的结构(如果它们具有相同的名称和相同的类型)则相等。如果 U 具有 T 的所有部分(可能还有其他),并且 U 的每个部分具有 T 的相应部分的子类型,则类型 U 是另一种类型 T 的子类型。

  • 具有结构化类型的语言为 OCaml/ReasonML、Haskell 和 TypeScript。

以下代码在名义类型系统中会产生类型错误(A 行),但在 TypeScript 的结构类型系统中是合法的,因为类 A 和类 B 具有相同的结构:

1class A {
2  name = 'A';
3}
4class B {
5  name = 'B';
6}
7const someVariable: A = new B(); // (A)

TypeScript 的 interface 在结构上也可以正常工作 —— 不必为了匹配而实现它们:

1interface Point {
2  x: number;
3  y: number;
4}
5const point: Point = {x: 1, y: 2}; // OK

进一步阅读

  • TypeScript 手册中的“类型兼容性”一章:https://www.typescriptlang.org/docs/handbook/type-compatibility.html

  • TypeScript 规范中的 “TypeRelationships” 部分:https://github.com/microsoft/TypeScript/blob/master/doc/spec.md#311-type-relationships

原文链接

https://2ality.com/2020/02/understanding-types-typescript.html

3yuquuV.jpg!web

2020年京程一灯全新课程体系即将推出,请保持关注。

愿你在新的一年里保持技术领先,有个好前程,愿你月薪30K。我们是认真的 ! BbquyaF.png!web

往期精彩回顾

面向开发人员的十大 NodeJS 框架

JavaScript 类完整指南

讲给前端的正则表达式

WebAssembly 正式成为 Web 的第四种语言

2020 年 Node.js 将会有哪些新功能

2020 年 Web 开发展望

从 JavaScript、ES6、ES7 到 ES10,你学到哪儿了?

15个 Vue.js 高级面试题

nmQvQvq.gif


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK