1

我有一个正在慢慢迁移到新ngrx语法的大型项目。我们有许多选择器,它们是这样的普通函数:

export function appDetailsSelector(state$: Observable<AppState>): Observable<AppDetails> {
    return state$.pipe(map((appState: AppState) => appState.appDetails));
}

新的选择器使用以下代码编写createSelector

export const selectUserConfig: MemoizedSelector<AppState, UserConfig> = createSelector(
  selectUserData,
  (userData: UserData) => userData.config,
);

这两个都使用相同的状态形状,但是我如何结合起来创建一个新的选择器,将这两者与createSelector

我知道我可以在组件代码中使用管道来执行此操作:

combineLatest([
  this.store.pipe(appDetailsSelector),
  this.store.select(selectUserConfig),
], (appDetails, userConfig) => ...projector fn code...);

但这不可重用,我需要完成它createSelector以避免在多个组件中重复此操作。如果appDetailsSelector是用它创建的,createSelector它看起来像这样:

export const getUserBookmarks = createSelector(
  appDetailsSelector,
  selectUserConfig,
  (appDetails: AppDetails, userConfig: UserConfig) => appDetails.useBookmarks ? userConfig.bookmarks : []
);

但是这个Argument of type 'MemoizedSelector<AppState, UserConfig, DefaultProjectorFn<UserConfig>>' is not assignable to parameter of type 'SelectorWithProps<Observable<AppState>, unknown, UserConfig>'.   Types of parameters 'state' and 'state' are incompatible.     Type 'Observable<AppState>' is missing the following properties from type 'AppState'...

我可以看到旧式选择器采用Observable<AppState>而新式选择器采用AppState;如何弥合这个差距并结合这两个选择器?

4

2 回答 2

1

您可以使用类型转换

export const getUserBookmarks = createSelector(
  appDetailsSelector as MemoizedSelector<AppState, UserConfig, DefaultProjectorFn<UserConfig>>,
  selectUserConfig as MemoizedSelector<AppState, UserConfig, DefaultProjectorFn<UserConfig>>,
  (appDetails: AppDetails, userConfig: UserConfig) => appDetails.useBookmarks ? userConfig.bookmarks : []
);

类型转换会将类型设置为相同的类型

于 2021-03-27T10:03:58.630 回答
0

没有办法使用Observable带有新createSelector语法的选择器。可观察选择器对可观察对象进行操作,而函数选择器直接对可观察对象中包含的数据进行操作;没有开箱即用的方法可以使它们一起工作。

请注意,可观察选择器实际上是变相的函数选择器;如果您需要维护您的经典选择器,只需将有状态逻辑移出到函数选择器中,并在每个上下文中使用正确的选择器。

export const appDetailsSelector = (state: AppState) => state.appDetails;

export const appDetailsObservableSelector = (state$: Observable<AppState>) =>
  state$.pipe(map(appDetailsSelector));
于 2021-03-26T18:09:52.743 回答