克服 Array<T> 和 IObservableArray<T> 的不兼容性

Defeating the Array<T> and IObservableArray<T> incompatibility

假设我的商店中有一些 属性 是某种类型的数组 MyTypedecorated with observable:

class MyStore {
    @observable array
}

我知道在正常世界中这应该是 Array<MyType>。但是当我以这种方式声明它时,

class MyStore {
    @observable array: Array<MyType>
}

然后我失去了方法.remove(item: MyType)。另一方面,如果我用 IObservableArray<MyType>

声明它
class MyStore {
    @observable array: IObservableArray<MyType>
}

然后我失去了合法地为这个道具分配 Array<MyType> 值的可能性(在 合法 我的意思是分配没有构造 ... as IObservableArray<MyType> - 这个的缺点方法太明显:很多不必要的代码,类型应该在使用时导入等)

我也尝试过使用并集和交集类型:

  1. 交集 (Array<MyType> & IObservableArray<MyType>) 在为该道具分配 Array<MyType> 值期间产生错误:Property 'spliceWithArray' is missing in type MyType.
  2. Union (Array<MyType> | IObservableArray<MyType>) 仍然导致方法丢失 .remove(item: MyType).

我是否遗漏或误解了什么?有什么合法的方法可以打败它吗?提前谢谢大家!


顺便说一句,我使用的mobx版本是4,因为我需要支持旧iPad,不幸的是

如何创建您自己的定制类型、扩展 Array class 并手动实现 IObservableArray 方法作为可选方法?

既然锁定了mobx@4.6.0,随着版本的升级,界面的维护没有问题。

这并不理想,但这是我能想到的唯一方法,它允许您分配数组并使用 .remove() 等方法。

我调用类型 MyExtendedObservableArray:

import {IArrayChange, IArraySplice, IArrayWillChange, IArrayWillSplice, IInterceptor, IObservableArray, Lambda, observable} from "mobx";

interface MyExtendedObservableArray<T> extends Array<T>{
    spliceWithArray?(index: number, deleteCount?: number, newItems?: T[]): T[];
    observe?(listener: (changeData: IArrayChange<T> | IArraySplice<T>) => void, fireImmediately?: boolean): Lambda;
    intercept?(handler: IInterceptor<IArrayWillChange<T> | IArrayWillSplice<T>>): Lambda;
    clear?(): T[];
    peek?(): T[];
    replace?(newItems: T[]): T[];
    find?(predicate: (item: T, index: number, array: IObservableArray<T>) => boolean, thisArg?: any, fromIndex?: number): T | undefined;
    findIndex?(predicate: (item: T, index: number, array: IObservableArray<T>) => boolean, thisArg?: any, fromIndex?: number): number;
    remove?(value: T): boolean;
    move?(fromIndex: number, toIndex: number): void;
    toJS?(): T[];
    toJSON?(): T[];
}

class MyType{}
let myType = new MyType();

class MyStore {
    @observable array: MyExtendedObservableArray<MyType> = [myType] 
    // no TSC compilation error
}

您需要使用下一个语法,这不会产生任何 TS 错误。您可以安全地使用 ArrayIObservableArray

的方法
class MyStore {
  readonly array = observable<MyType>([])

  @action
  getItems() {
    api.getItems<MyType[]>().then((response) => this.array.replace(response.data));
  }

  @action
  removeItem(item: MyType) {
    this.array.remove(item);
  }
}

readonly - 因为你大多不打算为 array 属性 做作业,比如 this.array = itemsFromServer

替换、移除 - IObservableArray

的方法