当构造函数不同时,无法识别 Angular ngrx 联合类型操作

问题描述 投票:0回答:2

下面显示了动作类和联合类型。但是,运行应用程序时无法识别这些操作。

export class Login implements Action {
  readonly type = LOGIN;
  constructor(
    public payload: {
      userID: string;
      email: string;
      token: string;
      expirationDate: Date;
    }
  ) {}
}

export class Logout implements Action {
  readonly type = LOGOUT;
  constructor() {}
}

export class LoginStart implements Action {
  readonly type: string = LOGIN_START;
  constructor(public payload: { username: string; password: string }) {}
}

export class LoginFail implements Action {
  readonly type: string = LOGIN_FAIL;
  constructor(public payload: string) {}
}

export type AuthActions = Login | Logout | LoginStart | LoginFail;

运行应用程序时,ngserve给出以下错误。

ERROR in src/app/auth/store/auth.reducer.ts:23:16 - error TS2339: Property 'payload' does not exist on type 'AuthActions'.
  Property 'payload' does not exist on type 'Logout'.

23         action.payload.userID,
                  ~~~~~~~
src/app/auth/store/auth.reducer.ts:24:16 - error TS2339: Property 'payload' does not exist on type 'AuthActions'.
  Property 'payload' does not exist on type 'Logout'.

24         action.payload.email,
                  ~~~~~~~
src/app/auth/store/auth.reducer.ts:25:16 - error TS2339: Property 'payload' does not exist on type 'AuthActions'.
  Property 'payload' does not exist on type 'Logout'.

25         action.payload.token,

有人可以提供有关如何在不更改构造函数的情况下解决此问题的线索吗?

我遵循了以下线程,但没有给出正确的解决方案。 无法识别打字稿可区分的联合类型

angular typescript ngrx union-types ngrx-reducers
2个回答
0
投票

如错误消息所示,给定属性 (

payload
) 在
Logout
上不存在。 作为某些情况下的经验法则,值得在
ActionWithPayload<T>
旁边使用
Action
实用程序类型,因为有些操作可能有有效负载,有些可能没有。

这个问题与架构本身有关,与实现无关。

如果添加给定的实用程序类型

ActionWithPayload<T>
,您可以用来检查给定实例是否具有属性
payload

所以首先你需要的是实用界面:


interface ActionWithPayload<T = any> {
  payload: T;
}

然后你需要一个实用函数来检查给定的对象是否是

ActionWithPayload<T>

的实例

function hasPayload(actionWithPayloadLike: any): actionWithPayloadLike is ActionWithPayload {
  return 'payload' in actionWithPayloadLike;
}

然后您可以使用它来检查给定实例是否具有正确的属性:


const loginFailAction: AuthActions = new LoginFail("test");
if(hasPayload(loginFailAction)) {
  alert(loginFailAction.payload);  // will show an alert
}


const logoutAction: AuthActions = new Logout();
if(hasPayload(logoutAction)) {
  alert(logoutAction.payload);  // wil not show an alert
}

Ofc,为了美化你的代码,在类中实现接口而不是

Action
误导性的东西会很棒。


0
投票

这个问题已经解决了。这里的问题是,“字符串”类型用于某些操作,但对于其他操作则不是。只需删除类型定义即可解决该问题。 更正:检查“类型”现在不是“字符串”。

export class LoginStart implements Action {
  readonly type = LOGIN_START;
  constructor(public payload: { username: string; password: string }) {}
}

export class LoginFail implements Action {
  readonly type = LOGIN_FAIL;
  constructor(public payload: string) {}
}
© www.soinside.com 2019 - 2024. All rights reserved.