将Flow注释添加到像这样的函数中的正确/首选方法是什么?
function addBar(foo) {
foo.bar = 10
return foo
}
我们说我有以下类型:
type Foo = { foo: string }
type FooBar = { foo: string, bar: number }
我希望该功能可以接收Foo
并返回FooBar
。
到目前为止,我提出的最佳解决方案是:
function addBar(foo: Foo): FooBar {
const fooBar: FooBar = { ...foo, bar: 10 }
return fooBar
}
创建对象的副本并依赖于rest属性。或者这个:
function addBar(foo: Foo): FooBar {
const fooBar: FooBar = (foo: any)
fooBar.bar = 10
return fooBar
}
需要一些hacky cast。
理论上,这应该是可以实现的,无需任何铸造或复制。但Flow的动态分析可以检测到这一点吗?还有其他方法更适合这种用例吗?
答案 0 :(得分:0)
您的问题在于foo
对象字面值,除非特别注释,否则它不会支持其他突变。
为了进一步简化您的示例,以下内容将引发流错误:
const hello = { hello: 'hello' };
hello.world = 'world';
18: hello.world = 'world';
^ property `world`. Property not found in
18: hello.world = 'world';
^ object literal
但以下情况不会:
const hello: { hello: 'hello', [someOtherKey: string]: mixed };
hello.world = 'world';
// no errors!
但是,允许"property variance"有效地解封hello
并将其转换为地图,如果您不想添加属性,则将其打开为静默类型错误。
另一种注释方法的简单方法是执行以下操作:
type FooBarType = {
foo: mixed,
bar?: number
}
function addBar(foo: FooBarType): FooBarType {
foo.bar = 10;
return foo;
}
addBar({ foo: 'hello' }); // no errors!
这确保了foo的类型可以支持添加bar。这与实际拥有该属性不同。您通常不希望您的方法绕过对象类型来改变它们的属性。相反,以能够支持突变的方式定义对象。否则使用函数方法,并返回一个新对象。以下内容可以让你保持密封:
function functionalAddBar(foo: Foo): FooBar {
return Object.assign({}, foo, { bar: 10 });
}