作者是 Dr. Axel Rauschmayer,号称”德国阮一峰“,本文原文来自于他的博客:https://2ality.com/2020/02/understanding-types-typescript.html,不熟悉他的可以关注一下他的博客。
以下是原文:
以下三个问题对于理解类型是如何工作的非常重要,需要从这两个角度中的每一个角度来回答。
myVariable
的类型 MyType
意味着什么?let myVariable: MyType = /*...*/;
Sourcetype
可以分配给 TargetType
吗?let source: SourceType = /*...*/;
let target: TargetType = source;
TypeUnion
是如何从Type1
、 Type2
和 Type3
衍生而来的?type TypeUnion = Type1 | Type2 | Type3;
从这个角度来看,类型是一组值:
myVariable
具有 MyType
类型,这意味着可以分配给 myVariable
的所有值都必须是集合 MyType
的元素。Sourcetype
可以分配给 TargetType
,那么 Sourcetype
是 TargetType
的子集。因此,TargetType
也允许SourceType
所允许的所有值。Type1
、 Type2
和 Type3
的联合类型是定义它们的集合在集合论中的并集。从这个角度来看,我们不关心值以及它们在执行代码时如何流动。相反,我们采取了一种更为静态的观点:
S
何时可以分配给目标类型 T
:S
和 T
都是一样的类型S
或者 T
是 any 类型。让我们考虑以下问题:
myVariable
的静态类型可以分配给 MyType
,那么 myVariable
就具有类型 MyType
SourceType
和 TargetType
是互相兼容的,那么SourceType
可以分配给 TargetType
类型系统一个有趣的特点是,同一个变量在不同的位置可以有不同的静态类型:
const arr = [];
// %inferred-type: any[]
arr;
arr.push(123);
// %inferred-type: number[]
arr;
arr.push('abc');
// %inferred-type: (string | number)[]
arr;
静态类型系统的职责之一是确定两个静态类型是否兼容:
这通常意味着要检查 U 是否是 T 的子类型。这种检查的两种方法(大致)是:
下面的代码在标准类型系统中产生类型错误(第 A 行) ,但在 Typescript 的结构类型系统中是合法的,因为类 A
和类 B
具有相同的结构:
class A {
name = 'A';
}
class B {
name = 'B';
}
const someVariable: A = new B(); // (A)
Typescript 的接口在结构上也能工作——它们不需要实现来匹配:
interface Point {
x: number;
y: number;
}
const point: Point = {x: 1, y: 2}; // OK
如果翻译得不对的地方希望您可以帮忙指出来。
[1]
Chapter “Type Compatibility” in the TypeScript Handbook: https://www.typescriptlang.org/docs/handbook/type-compatibility.html
[2]
Section “TypeRelationships” in the TypeScript Specification: https://github.com/microsoft/TypeScript/blob/master/doc/spec.md#311-type-relationships