用union键入条件属性

时间:2017-07-25 10:44:45

标签: flowtype

我在自定义Component ES6类上定义了以下方法,该类采用具有component属性的对象。如果该属性是Component的实例,则会将其分配给ref,否则会创建一个包含elopts属性的新实例:

setRef({ id, component, el, opts = {}, props = {} }: refConstructorType | refInstanceType): Promise<Component> {
    let ref: Component;

    if (component instanceof Component) { 
         ref = component
    } else {
        ref = new component(el, opts);
    }
}       

refConstructorTyperefInstanceType的类型定义为:

type refInstanceType = {|
    component: Component,
    id: string,
    props?: {}
|};

type refConstructorType = {|
    component: typeof Component,
    id: string,
    el: Element,
    opts ?: {[option_ke: string]: string},
    props ?: {}
|};

无论如何,flowtype都在抱怨:

86:     setRef({ id, component, el, opts = {}, props = {} }: refConstructorType | refInstanceType): Promise<Component> {
                    ^^^^^^^^^ Component. This type is incompatible with
86:     setRef({ id, component, el, opts = {}, props = {} }: refConstructorType | refInstanceType): Promise<Component> {
                    ^^^^^^^^^ class type: Component

src/index.js:86
86:     setRef({ id, component, el, opts = {}, props = {} }: refConstructorType | refInstanceType): Promise<Component> {
                    ^^^^^^^^^ class type: Component. This type is incompatible with
86:     setRef({ id, component, el, opts = {}, props = {} }: refConstructorType | refInstanceType): Promise<Component> {
                    ^^^^^^^^^ Component

src/index.js:86
86:     setRef({ id, component, el, opts = {}, props = {} }: refConstructorType | refInstanceType): Promise<Component> {
                                ^^ property `el`. Property not found in
86:     setRef({ id, component, el, opts = {}, props = {} }: refConstructorType | refInstanceType): Promise<Component> {
                                                                                ^^^^^^^^^^^^^^^ object type

src/index.js:86
86:     setRef({ id, component, el, opts = {}, props = {} }: refConstructorType | refInstanceType): Promise<Component> {
                                    ^^^^ property `opts`. Property not found in
86:     setRef({ id, component, el, opts = {}, props = {} }: refConstructorType | refInstanceType): Promise<Component> {
                                                                                ^^^^^^^^^^^^^^^ object type

有关如何解决此问题的任何提示?

更新26/07/2017

按照建议的模式,我最终得到了以下精炼代码:

setRef(refCfg: refConstructorType | refInstanceType): Promise<Component> {

    let ref: Component;

    if (!isPlainObject(refCfg)) {
        throw new Error('Invalid reference configuration');
    }

    if (refCfg.component instanceof Component) {
        ref = refCfg.component;
    } else if (typeof refCfg.component === 'function' && refCfg.el) {
        const { el, opts, component } = refCfg;
        ref = new component(el, opts); //eslint-disable-line new-cap
    } else {
        throw new Error('Invalid reference configuration');
    }
    // ....
}

1 个答案:

答案 0 :(得分:1)

这是一个相当复杂的情况,但解决这个问题的安全方法是不解构。

您将Flow置于要求其创建类型为component的变量Component | typeof Component的位置,并询问该联合类型是否对refConstructorType.component有效且有效反对refInstanceType.component

  • Component == Component | typeof Component
  • typeof Component == Component | typeof Component

基本上,通过解构,它隐含地失败了“一进一出”:https://flow.org/en/docs/types/unions/#toc-union-types-requires-one-in-but-all-out

这就是为什么你看到Flow抱怨它两次。

一旦你解决了这个问题,其他错误最有可能通过确保Flow能够准确区分你的if / else中的不同条件来解决。