UK_Kefka
UK_Kefka

Reputation: 251

TypeScript - How to ensure value is a certain string?

I have the following;

type AppDisplay = "MainMenu" | "Game" | "GameOver";

interface AppState {
  appDisplay: AppDisplay
}

const initialAppState : AppState = {
  appDisplay: "MainMenu"
}

type ActionType = {
  type: "DisplayMenu" | "DisplayGame" | "DisplayGameOver";
}

const appStateReducer = (state : AppState, action : ActionType) => {
  switch (action.type) {
    case "DisplayMenu":
      return {
        appDisplay: "MainMenu"
      }
    case "DisplayGame":
      return {
        appDisplay: "Game"
      }
    case "DisplayGameOver":
      return {
        appDisplay: "GameOver"
      }
  }
}

The above code doesn't work, because the assignments in appStateReducer are of type String, and TS doesn't recognise them as being of type AppDisplay. How can I ensure that appDisplay can only be assigned as "Game", "GameOver" or "MainMenu"?

Upvotes: 0

Views: 667

Answers (2)

Romi Halasz
Romi Halasz

Reputation: 2009

As Oles mentioned, you can specify the return type of your function, but you can also simplify some aspects of your code:

You can define an enum with your desired values:

enum AppDisplay {
    MAIN_MENU,
    GAME,
    GAME_OVER
}

You can use this enum when defining the AppState interface:

interface AppState {
    appState: AppDisplay
}

The same idea can be applied to ActionType:

enum ActionType {
    DIPLAY_MENU,
    DISPLAY_GAME,
    DISPLAY_GAME_OVER
}

Using enums allows you do define specific values, without caring about the actual value type (string, number etc.).

Finally, your reducer function can look something like this (small remark - the state parameter doesn't seem to be used in your code):

const appStateReducer = (action: ActionType): AppDisplay => {
    switch(action) {
        case ActionType.DISPLAY_MENU: 
            return AppDisplay.MAIN_MENU;

        case ActionType.DISPLAY_GAME: 
            return AppDisplay.GAME;

        case ActionType.GAME_OVER: 
            return AppDisplay.DISPLAY_GAME_OVER;

    }
}

Hope you've found this helpful. Cheers.

Upvotes: 2

Oles Savluk
Oles Savluk

Reputation: 4345

You will need to add return type to this function:

const appStateReducer = (state : AppState, action : ActionType): AppState => {
  ...
}

or you could also define returned object type as const:

return { ... } as const

Upvotes: 1

Related Questions