Flow,object literal与union不兼容

时间:2017-09-22 18:30:05

标签: javascript flowtype

如果我有一个函数返回一个包含数据库信息的对象或一个像这样的空对象:

getThingFromDB: async function(id:string):Promise<EventObj|Empty>{
    const fromDB = await dao.getEvent(id);
    if(fromDB && fromDB.length){
        return fromDB[0];
    }
    return {};

}

我收到很多Flow错误,如:

return {};
       ^^ object literal. This type is incompatible with
getThingFromDB: async function(id:string):Promise<EventObj|Empty>{                                                                                
                                                  ^^^^^^^^^^^^^^ union: EventObj | Empty

或者

getThingFromDB: async function(id:string):Promise<EventObj|Empty>                                                                                      
                                                  ^^^^^^^^ property `id`. Property not found in
return {};
       ^^ object literal

以下是我声明的对象类型。

declare type EventObj = {
    id:string,
    name:string,
    urlName:string
};

declare type Empty = {||};

我错过了什么?如何正确满足这些错误。

1 个答案:

答案 0 :(得分:1)

可能的补丁包括封闭/冻结空Object字面值。但这只会绕过潜在的问题:您已经定义了一个精确的Object类型,尽管您只需要一个密封的类型:

type Empty = {};

let o = {};
let p = {foo: true};
let q: Empty = {};

o.foo = true; // type checks
p.bar = true; // type error
q.foo = true; // type error

您可以看到只有空对象文字是流中未密封的Object类型。此时不需要精确的Object类型,您可以安全地从{||}中删除确切的类型注释。那对它们有用吗?

type Foo = {|foo: boolean|};
type Bar = {bar: boolean};

const f = (o: Foo) => o;
const g = (o: Bar) => o;

f({foo: true, bar: true}); // type error
let o = g({foo: true, bar: true}); // type checks

o.foo; // type error

使用精确的Object类型,您可以更好地控制宽度子类型。

但是,宽度子类型有自己的缺陷,因为它会删除类型信息,因为您可以通过失败的属性访问o.foo看到。