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

问题描述 投票:23回答:2

qazxsw poi和qazxsw poi声明似乎做同样的事情。你什么时候用另一个?

interface

VS

type
javascript flowtype
2个回答
34
投票

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

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

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

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

希望这可以帮助!


1
投票

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

type Fooable = {
  foo(): string
}

但是,如果我们定义一个等效的interface Fooable { foo(): string } 类型,我们的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"
    }
}

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

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`.

参考文献:

  1. interface Foo { +property: string | number } let foo: Foo = { property: 42 } // Good!
  2. type Foo = { property: string | number } // Good! let foo: Foo = { property: 42 }
© www.soinside.com 2019 - 2024. All rights reserved.