使用 NgRx ActionCreator 作为参数的方法的正确类型声明

Correct type declaration for method with NgRx ActionCreator as parameter

有一个动作,使用 NgRx createAction() 方法创建:

import { createAction, props } from '@ngrx/store';

export const Login = createAction(
  '[Login] Login',
  props <{email: string, password: string}>()
);

我想使用一种方法创建服务,该方法将使用 createAction() 方法创建的操作作为参数,returns 将此操作作为其属性之一的对象。

现在看起来像:

import { ActionCreator, ActionsSubject } from '@ngrx/store';

interface ActionWithProgress<T> {
  progress: boolean;
  action: T;
}

export class ListenerService {
  constructor(private dispatcher: ActionsSubject) { }

  public isInProgress(currentAction: ActionCreator): Observable<ActionWithStatus<ActionCreator>> {
    return this.dispatcher.pipe(
      filter((action: Action) => action.type === currentAction.type),
      map((action: Action) => ({progress: true, action: currentAction}))
    );
  }
}

但在这种情况下,TypeScript 会丢失操作类型 属性 并且无法处理这样的错误:

this.loginEmail$ = this.listenerService
  .isInProgress(LoginActions.Login)
  .pipe(
    // Want to see here TypeScript error: property 'name' doesn't exist in Login action
    map((actionWithProgress) => actionWithProgress.action.name)
  );

我尝试探索:

import { ofType } from '@ngrx/effects';

其声明:

export declare function ofType<E extends Extract<U, {
    type: T1;
}>, AC extends ActionCreator<string, Creator>, T1 extends string | AC, U extends Action = Action, V = T1 extends string ? E : ReturnType<Extract<T1, AC>>>(t1: T1): OperatorFunction<U, V>;

但是为了与旧版本的 NgRx 向后兼容,它似乎过载了。

所以我需要此方法的正确类型以防止丢失操作 属性 类型。

试试这个:

  isInProgress<
    T1 extends ActionCreator,
    V = ReturnType<T1>
  >(currentAction: T1): Observable<ActionWithProgress<V>>

  isInProgress(currentAction: ActionCreator): Observable<ActionWithProgress<Action>> {
    return this.dispatcher.pipe(
      filter((action: Action) => action.type === currentAction.type),
      map((action: Action) => ({ progress: true, action: action }))
    );
  }

对我有用。