class vs 输入 Flow

class vs type in Flow

在 Flow 中,为什么要使用 class 而不是类型?

type Point = {x: number; y: number};
class Point = {x: number; y: number};

在您的示例中,您只需要一个类型。

但是如果你想定义方法,你会想要使用 class。

class Point {
    x: number;
    y: number;
    constructor(x, y) {this.x = x; this.y = y;}
    distance_from_origin(): number { /* code goes here */ }
    angle_from_origin(): number { /* code goes here */ }
}

p: Point = new Point(2, 3);
d = p.distance_from_origin()

类型是用于编译时检查的流程功能,可帮助您捕获代码中的错误。它们完全从 运行 之前的代码中删除。

类 根本不是 Flow 功能(尽管 Flow 理解 classes - 你创建的每个 class 也定义了一个 Flow 类型) - 它们是ES6,下一个版本JavaScript。 Babel 是从您的代码中剥离 Flow 类型以使其有效的程序 JavaScript,它还可以将您的 classes 转换为 ES5 兼容代码。

the documentation 中所示,流以不同方式处理对象和 classes。 (即使你正在迁移到 ES5,流检查也会在此之前发生。)

A class 按名称比较。对象类型按结构比较。

事实上,type alias只是类型结构注解的一种较短的写法。它就像一个包含较长表达式的变量。

type A = {wow: number}
type B = {wow: number}

let a:A = {wow: 1}
let b:B = {wow: 2}
; [a, b] = [b, a] // fine
console.log(a, b) // > { wow: 2 } { wow: 1 }

class C {
  constructor (x: number) { this.wow = x }
  wow: number
}
class D {
  constructor (x: number) { this.wow = x }
  wow: number
}
let c:C = new C(3)
let d:D = new D(4)

c = d // ERROR: D This type is incompatible with C
d = b // ERROR: object type This type is incompatible with D

如您所见,两个具有相同结构的class不兼容。

注意:有多种方法可以使不同的 classes 兼容,例如 Union Types or Interfaces

类 提供名义类型,而对象类型提供结构类型。

假设我想引入一个带有 xy 字段的 Vector 类型。当我去创建我的 add(p: Point, v: Vector): Point 函数时,结构类型被证明是不合适的,例如

type Point = {x: number, y: number};
type Vector = {x: number, y: number};

function add(p: Point, v: Vector): Point {
  return {x: p.x + v.x, y: p.y + v.y};
}

const p1: Point = {x:0, y:5};
const p2: Point = {x:2, y:3};
const v: Vector = add(p1, p2); // This is not an error in Flow

将其与 classes 的名义类型版本进行对比:

class Point { x: number; y: number;
  constructor(x: number, y: number) {
    this.x = x;
    this.y = y;
  }
}
class Vector { x: number; y: number;
  constructor(x: number, y: number) {
    this.x = x;
    this.y = y;
  }
}

function add(p: Point, v: Vector): Point {
  return new Point(p.x + v.x, p.y + v.y);
}

const p1: Point = new Point(0, 5);
const p2: Point = new Point(2, 3);
const v: Vector = add(p1, p2); // Error: p2 isn't a Vector

(实际上,您可能会将 add 作为点 class 上的方法附加,但我已将其与对象类型示例的并行结构分开。)

请注意,您可以使用标记字段从对象类型中获取一些名义类型的表象,例如

type Point = { tag: "point", x: number y: number };
type Vector = { tag: "vector", x: number, y: number };

如果您的 class 没有任何方法,那么我建议您这样做。