【问题标题】:class vs type in Flow类与流中的类型
【发布时间】:2017-02-24 00:38:28
【问题描述】:

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

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

【问题讨论】:

  • 你的语法有点错误。 class Point {...} 用于声明,let Point = class {...} 用于表达式,其中类表达式必须包含名称,例如let Point = class P {...},如果您想从其自身的主体中引用该类。

标签: flowtype


【解决方案1】:

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

假设我想引入带有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

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

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 作为方法附加到点类上,但我已将其与对象类型示例分开以用于并行结构。)

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

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

如果你的类没有任何方法,那么我建议这是要走的路。

【讨论】:

    【解决方案2】:

    正如the documentation 中所见,flow 以不同的方式对待对象和类。 (即使你正在转换到 ES5,流检查也会在此之前发生。)

    通过名称比较一个类。对象类型按结构进行比较。

    其实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
    

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

    注意:有一些方法可以使不同的类兼容,例如Union TypesInterfaces

    【讨论】:

      【解决方案3】:

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

      但是如果你想定义方法,你会想使用一个类。

      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 理解类 - 您创建的每个类也定义了一个 Flow 类型) - 它们是 ES6 的一个特性,即 JavaScript 的下一个版本。 Babel 是从您的代码中去除 Flow 类型以使其成为有效 JavaScript 的同一程序,它也可以将您的类转换为 ES5 兼容的代码。

      【讨论】:

        猜你喜欢
        • 2020-06-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多