interface
和type
声明似乎做同样的事情。你何时使用其中一个?
type Fooable = {
foo(): string
}
VS
interface Fooable {
foo(): string
}
答案 0 :(得分:34)
这是一个很好的问题。理想情况下,接口和对象类型之间没有区别。实施后,它们之间存在一些(通常是微妙的)差异。
最大的区别是Flow认为在接口上声明的方法是"只读。"这允许子类型与w.r.t协变。方法,这是一种非常常见的继承层次结构模式。
随着时间的推移,我希望看到Flow统一这些概念,但在此之前,这是我在接口和对象类型之间进行选择的经验法则:
希望这有帮助!
答案 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 }
参考文献: