reactjs - React Redux handlingstyper ved hjelp av typeof


i det nedenfor, kodehandlingstype (action som SucceededAction) er spesifisert i reduceren og ting fungerer, men hvis jeg fjerner (som SucceededAction) får jeg en feil 'payload eksisterer ikke på typen 'SucceededAction | FailedAction'.

Nå hvis jeg erstatter konstantene med --

type_SUCCEEDED:'type_SUCCEEDED',type_FAILED:'type_FAILED' og bruk dem som type_FAILED og type_SUCCEEDED i stedet for type.FAILED, type.SUCCEEDED, det fungerer uten typekonvertering.

Så, i koden nedenfor tror jeg typeof ikke fungerer for handlingene mine, noe som gjør at jeg må typekaste i reducerne. Vil vite den eksakte årsaken til dette. Vennligst hjelp hvis du vet grunnen og hjelp meg med å finne feilen i koden nedenfor.

Takk.

//constants
export const type = {
    SUCCEEDED: 'type_SUCCEEDED',
    FAILED: 'type_FAILED'
};

export interface SucceededAction {
  readonly type: typeof type.SUCCEEDED;
  readonly payload: string;
}

export interface FailedAction {
  readonly type: typeof type.FAILED;
}

//actions
export const Succeeded = (payload: string): SucceededAction => ({
  type: type.SUCCEEDED,
  payload,
});

export const Failed = (): FailedAction => ({
  type: type.FAILED,
});

//reducer
export const myReducer = (
  state: string = '',
  action:
    | SucceededAction
    | FailedAction,
): string => {
  switch (action.type) {
    case type.SUCCEEDED:
      return (action as SucceededAction) //type specified
        .payload;
    case type.FAILED:
      return state;
    default:
      return state;
  }
};

Svar #1

Akkurat nå ser TypeScript både type.SUCCEEDED og type.FAILED som string. Dette betyr at handlingen din, SucceededAction | FailedAction, bare er { readonly type: string; readonly payload: string; } | { readonly type: string; }.

Typenavnene må være strengbokstaver typer for å kunne skille foreningen. Dette kan gjøres på to måter:

1) Enum-typer

Du kan gjøre din type-variabel til en enum:

export enum type {
    SUCCEEDED = 'type_SUCCEEDED',
    FAILED = 'type_FAILED'
};

En TypeScript-enum er både en verdi og en type, så du trenger ikke å bruke typeof lenger. Du kan bruke den som type direkte, slik:

export interface FailedAction {
  readonly type: type.FAILED;
}

Dokumenter: Enum

Dette er akkurat den typen situasjon som string-enum er laget for. Etter min mening er dette den bedre tilnærmingen, men det finnes en annen løsning som er verdt å nevne.

2) som const

Du kan erklære variabelen som en bokstavelig skrivebeskyttet med as const:

export const type = {
    SUCCEEDED: 'type_SUCCEEDED',
    FAILED: 'type_FAILED'
} as const;

Docs: const-påstander