什么时候在流中使用类型别名的接口?

时间:2016-04-28 02:27:49

标签: javascript flowtype

interfacetype声明似乎做同样的事情。你何时使用其中一个?

type Fooable = {
  foo(): string
}

VS

interface Fooable {
 foo(): string
}

2 个答案:

答案 0 :(得分:34)

这是一个很好的问题。理想情况下,接口和对象类型之间没有区别。实施后,它们之间存在一些(通常是微妙的)差异。

最大的区别是Flow认为在接口上声明的方法是"只读。"这允许子类型与w.r.t协变。方法,这是一种非常常见的继承层次结构模式。

随着时间的推移,我希望看到Flow统一这些概念,但在此之前,这是我在接口和对象类型之间进行选择的经验法则:

  • 使用对象类型来描述在应用程序中传递的大部分数据包,例如React组件的props / state,Flux / Redux操作,类似JSON的东西。
  • 使用接口描述类似服务的接口。通常这些主要是方法,例如Rx.Observable / Observer,Flux / Redux存储,抽象接口。如果类实例可能是您的类型的居民,您可能需要一个接口。

希望这有帮助!

答案 1 :(得分:1)

Flow中的接口可用于确保类实现某些方法和属性。例如:

interface IFly {
   fly(): string
}

// Good!
class Duck implements IFly {
    fly() {
        return "I believe I can fly"
    }
}

// Bad! Cannot implement `IFly` with `Duck` because number is incompatible with string in the return value of property `fly`.
class Duck implements IFly {
    fly() {
        return 42
    }
}

// Bad! Cannot implement `IFly` with `Duck` because property `fly` is missing in `Duck` but exists in `IFly`.
class Duck implements IFly {
    quack() {
        return "quack quack"
    }
}

但是,如果我们定义等效的IFly类型,我们的Duck类将无法实现它:

type IFly = {
  fly(): string
}

// Cannot implement `Fly` because it is not an interface.
class Duck implements Fly {
    fly() {
       return "I believe I can fly"
    }
}

此外,类型和接口之间还有细微的差别。

默认情况下,界面属性为不变。例如:

interface Foo {
    property: string | number
}

let foo: Foo = { property: 42 } // Cannot assign object literal to `foo` because number is incompatible with string in property `property`.

要使接口属性协变,它们必须设为只读:

interface Foo {
    +property: string | number
}

let foo: Foo = { property: 42 } // Good!

另一方面,对于类型,Flow不会抱怨:

type Foo = {
    property: string | number
}

// Good!
let foo: Foo = { property: 42 }

参考文献:

  1. Flow interfaces
  2. Type variance