假设我有一个像这样的Flow typedef:
type ApiResponse = {
+foo?: { [string]: Object },
+bar?: { [string]: Object},
}
type FooApiResponse = {
foo: { [string] : Object }
}
并且具有以下签名的函数:
function does_not_accept(baz : ApiResponse) : void {
if(baz.foo) { console.log(baz.foo) }
}
function also_does_not_accept(baz: $Shape<ApiResponse>) : void {
if(baz.foo) { console.log(baz.foo) }
}
在参数位置使用FooApiResponse
调用其中一个函数失败。
第一个失败,bar
缺少属性错误(即使它是可选的。)
第二个失败是因为bar
是只读的(即使它从未被写入。)
我如何编写一个接受ApiResponse
的各种“子类型”的函数
像$Supertype<ApiRsponse>
这样的参数类型签名有效 - 但我不明白为什么。 FooApiResponse
和ApiResponse
之间的子/超级关系是如何解决的?这叫什么问题?我甚至不知道谷歌的词汇来回答这个问题。
$Shape
和$Supertype
是实验性的特征。如果他们没有做你想做的事情,或者希望他们做什么,可以考虑打开一个问题。
除了Object之外,ApiResponse
没有超类型。它可能有效,因为你正在剥离定义的属性 - 与使用{}
相同。我怀疑它打算用于使用extends
的类类型。
如果你专门为FooApiResponse
键入一个对象文字,那么即使它们具有相同的形状,你也不希望它被接受为ApiResponse
。您需要在参数类型上使用交集以允许它接受。
function accept(baz: ApiResponse | FooApiResponse) {}
我认为显示的Flow错误是无益的,所以可能会为此打开一个问题。表示只读的+
似乎也混淆了错误,但你没有在FooApiResponse
定义中使用它,因此类型与foo
不兼容。