Skip to content

从两个角度看Typescript中的类型是什么

Posted on:March 3, 2020 at 10:09 AM

0. 作者以及原文介绍

作者是 Dr. Axel Rauschmayer,号称”德国阮一峰“,本文原文来自于他的博客:https://2ality.com/2020-02/understanding-types-typescript.html,不熟悉他的可以关注一下他的博客。

1. 每个角度都从这三个问题来解释

以下三个问题对于理解类型是如何工作的非常重要,需要从这两个角度中的每一个角度来回答。

  1. myVariable 的类型 MyType 意味着什么?
let myVariable: MyType = /*...*/;
  1. Sourcetype 可以分配给 TargetType 吗?
let source: SourceType = /*...*/;
let target: TargetType = source;
  1. TypeUnion 是如何从 Type1Type2 Type3 衍生而来的?
type TypeUnion = Type1 | Type2 | Type3;

2. 角度 1: 类型是一组值

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

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

  2. 如果 Sourcetype 可以分配给 TargetType,那么 SourcetypeTargetType 的子集。 因此,TargetType 也允许 SourceType 所允许的所有值。

  3. 类型 Type1Type2Type3的联合类型是定义它们的集合在集合论中的并集。

3. 角度2: 类型兼容关系

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

让我们考虑以下问题:

  1. 如果 myVariable 的静态类型可以分配给 MyType ,那么 myVariable 就具有类型 MyType
  2. 如果 SourceTypeTargetType 是互相兼容的,那么SourceType可以分配给 TargetType
  3. 联合类型的工作方式是通过类型关系成员定义的。

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

const arr = [];
// %inferred-type: any[]
arr;

arr.push(123);
// %inferred-type: number[]
arr;

arr.push('abc');
// %inferred-type: (string | number)[]
arr;

4. 标准类型系统和结构类型系统

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

这通常意味着要检查 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

5. 进一步阅读

如果翻译得不对的地方希望您可以帮忙指出来。