Правильное объявление типа для метода с NgRx ActionCreator в качестве параметра - PullRequest
0 голосов
/ 20 сентября 2019

Существует действие, созданное с использованием метода createAction () NgRx:

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

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

Я хочу создать службу с методом, который принимает действие, созданное с помощью метода createAction (), и возвращает объект с этимaction как одно из его свойств.

Теперь это выглядит следующим образом:

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 теряет свойство типа action и невозможно обрабатывать ошибки, подобные этой:

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.

Поэтому мне нужен правильный тип для этого метода, чтобы предотвратить потерю типа свойства action.

1 Ответ

2 голосов
/ 23 сентября 2019

Попробуйте это:

  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 }))
    );
  }

Сработало для меня.

...