0

I want to safely access a property on a Union Type (all options are interfaces) set by external library(mobx).

 Cannot call observe because:
 Either property added is missing in IArrayChange [1] but exists in IArraySplice [2] in the first argument.
 Or property added is missing in IObjectChange [3] but exists in IArraySplice [2] in the first argument.

 142│     observe(thisContainer.items, (change: IArraySplice<any>) => {
 143│        change.added.forEach((item: Item) => this.observeChanges(item));
 145│     });
 146│   }
 147│

 node_modules/mobx/lib/mobx.js.flow
  356│     listener: (change: IArrayChange<T> | IArraySplice<T>) => void,

  372│     listener: (change: IObjectChange) => void,

I have tried:

  • using conditionals to check whether .added exists before running change.added.iterator. if (change.added){ && if ('added' in change) {

  • using a condition to check that the universally available property type is set to splice. This should ensure that the property added is also available. change.type === 'splice' && change.added....

The docs suggest is typical to write conditions for type checks https://flow.org/en/docs/types/unions/ But I am unsure of the best way to do this w/ an external library's interfaces. Authoring functions such as Interface type check with Typescript feels heavier than I'd like for meeting the rules pre-commit type checker.

How should this be done?

skyboyer
  • 22,209
  • 7
  • 57
  • 64
hbrannan
  • 153
  • 1
  • 7

1 Answers1

0

Working solution:

observe(thisContainer.items, (change: IArraySplice<any> | IArraySplice<T>) => {
    if (change.type === 'splice') {
        change.added.forEach((item: Item) => this.observeChanges(item));
    }
});

Explanation:

Though the error message focuses on the existence of the property, the error is triggered b/c the passed argument is not necessarily as anticipated.

Since mobx IObservableArray changes can generate either IArraySplice<T> or IArraySplice<T>, the Flow types need to account for either.

Once that is handled, properties available on both expected are available for refinement.

For reference, the implementation the mobx types:

export interface IArrayChange<T> {
    type: "update",
    object: IObservableArray<T>,
    index: number,
    newValue: T,
    oldValue: T
}

export interface IArraySplice<T> {
    type: "splice",
    object: IObservableArray<T>,
    index: number,
    added: T[],
    addedCount: number,
    removed: T[],
    removedCount: number
}
hbrannan
  • 153
  • 1
  • 7