ngrx/store 使用带有 class 的 createFeatureSelector 时抛出 运行 时间错误

ngrx/store throws run time error when using createFeatureSelector with a class

我的应用程序是基于 Angular、Immutable.js、NgRx 的最新版本构建的; 我想利用 NGRX 的 createFeatureSelectorcreateSelector。但是,我好像只能select 件的存储按字符串。我已经提取了相关的代码片段(我认为)。我还在下面添加了一个 plunker link 来说明这个问题。

当应用程序启动时,它会抛出 Uncaught TypeError: <CLASS> is not a constructor 的错误。

我尝试过的方法和产生的症状:

  1. 如果我将有问题的文件移到 initialState 文件中,reducer 将在该文件中获得默认状态,错误将移动到构造链下的下一个 class。在下面的示例中,CopyRollbackState(下面的代码)是一个 class,它包含两个子 classes CopyRollbackRemovables$CopyRollbackConfirm$;如果我将第一个复制到 initialState 文件中,错误将移动到第二个。

  2. 如果我用不可变映射替换顶层 class、CopyRollbackState,应用程序无法 运行 并出现相同的错误。

  3. 如果我从我的状态初始化中删除所有硬 classes,例如使用 immutable.fromJS() 方法,错误消失。但是,我想在商店中使用实际的 classes。

感谢您的帮助。

例如

/** provider.ts */

// this works 
this.copyRollbackRemovables$ = this._store.select('copyRollbackRemovables');

// this fails with the below error
// this is one of the methods of ngrx i want to use !!
this.copyRollbackRemovables$ = this._store.pipe(select(_RootReducer.getRollbackRemovables));

_

/** _RootReducer.ts */

export const appState: ActionReducerMap<AppState> = {
    ...
    copyRollbackRemovables: fromCopyRollback.copyRollbackEntitiesReducer,
    ...
}

export const getRollbackRemovables = 
    createFeatureSelector<CopyRollbackRemovables$>('copyRollbackRemovables');

_

/** fromCopyRollback.ts reducer */

export function copyRollbackEntitiesReducer(
  state: any = initialState.get('copyRollbackEntities'),
  action: Action
): CopyRollbackRemovables$ {
  switch (action.type) {

    default:
      break;
  }
  return state;
}

_

/** model.ts */

const copyRollbackStateRecord = Record({
  copyRollbackEntities: null,
  copyRollBackConfirm: null,
});

interface ICopyRollbackState {
  copyRollbackEntities: CRM.ICopyRollbackRemovables$,
  copyRollBackConfirm: CRM.ICopyRollbackConfirm$
}

export class CopyRollbackState extends copyRollbackStateRecord implements ICopyRollbackState {
  copyRollbackEntities: CRM.CopyRollbackRemovables$;
  copyRollBackConfirm: CRM.CopyRollbackConfirm$;
  constructor(config: ICopyRollbackState) {
    super(Object.assign({}, config, {
      copyRollbackEntities: config.copyRollbackEntities && new CRM.CopyRollbackRemovables$(config.copyRollbackEntities),
      copyRollBackConfirm: config.copyRollBackConfirm && new CRM.CopyRollbackConfirm$(config.copyRollBackConfirm)
    }));
  };
}

export const initialState: CopyRollbackState = new CopyRollbackState({
  copyRollbackEntities: {
    meta: {
      loading: false
    },
    byBatchId: Map({})
  },
  copyRollBackConfirm: {
    meta: {
      loading: false
    },
    data: {
      templateItemIds: [],
      rollBackConfirmer: false,
      rollBackReason: ''
    }
  }
});

// CRM.ts, similar extend and interface as above class
export class CopyRollbackRemovables$ extends copyRollbackRemovablesRecord$ implements ICopyRollbackRemovables$ {
  meta: IPagedMeta;
  byBatchId: Map<string, List<CopyRollback>>;
  constructor(config: ICopyRollbackRemovables$) {
    super(Object.assign({}, config, {
      meta: config.meta && new PagedMeta(config.meta),
      byBatchId: config.byBatchId && Map(config.byBatchId)
    }));
  }
}

这是错误中引用的转译代码。

var CopyRollbackState = (function (_super) {
    __extends(CopyRollbackState, _super);
    function CopyRollbackState(config) {
        return _super.call(this, Object.assign({}, config, {
            copyRollbackEntities: config.copyRollbackEntities && new CRM.CopyRollbackRemovables$(config.copyRollbackEntities),
            copyRollBackConfirm: config.copyRollBackConfirm && new CRM.CopyRollbackConfirm$(config.copyRollBackConfirm)
        })) || this;
    }
    ;
    return CopyRollbackState;
}(copyRollbackStateRecord));

我构建了一个 bare minimum Plunker 来显示错误。当 plunk 加载时,您可以在控制台中看到错误。对于我的应用程序,该错误会阻止应用程序加载。

我解决这个问题的方法是将所有 Class 定义移动到一个文件中。在我的例子中,我在 *.store.ts 文件中有 class 定义,它依赖于 *.model.ts 文件中的 class 定义。将所有定义移动到两者之一解决了这个问题。

仍然不确定实际问题出在哪里。也许 DI 很难找到正确的 class.