What is the most efficient method for designing a nested object with two levels of enums, allowing for some enum values to be optional?

As an illustration

enum Size {
  Small: 'smallSize'
  Medium: 'mediumSize'
  Large: 'largeSize'
}

enum Weekday {
  Monday: 'Monday'
  Tuesday: 'Tuesday'
  ...
}


// Need only Size.Medium and Size.Large, as well as from 1 to 7 entries for Weekdays
const mapping: { [size in Size]?: { [weekday in Weekday]? : MenuType } = {
  [Size.Medium] : { Weekday.Tuesday : <menuObject> }
  [Size.Large] : { 
    Weekday.Monday : <menuObject>
    Weekday.Friday : <menuObject>
  }
}

Upon attempting to retrieve the menu using

const menu = mapping[Size.Large][Weekday.Monday]
, an error occurs indicating that Object is possibly undefined.

What would be the most effective approach to establish this mapping while preserving strong typing?

Answer №1

According to @Linda Paiste, this behavior is considered normal.

Using the operator ?: indicates that the subsequent key may or may not be defined (undefined).

Therefore, when TypeScript traverses your mapping object, there is no guarantee that the data behind Size.Large will be defined, which is why it results in an error.


You have two options:


Option 1: Make every key mandatory like so:

playground

enum Size {
  Small = 'small',
  Medium = 'medium',
  Large = 'large',
};

enum Weekday {
  Monday = 'Monday',
  Tuesday = 'Tuesday',
  Friday = 'Friday',
};

type MenuType = {};

const mapping: {
     [size in Size]: { 
         [weekday in Weekday] : MenuType;
     };
} = {
    [Size.Small]: { 
        [Weekday.Monday]: {},
        [Weekday.Tuesday]: {},
        [Weekday.Friday]: {},
    },

    [Size.Medium]: { 
        [Weekday.Monday]: {},
        [Weekday.Tuesday]: {},
        [Weekday.Friday]: {},
    },

    [Size.Large]: { 
        [Weekday.Monday]: {},
        [Weekday.Tuesday]: {},
        [Weekday.Friday]: {},
    },
};

const menu = mapping[Size.Large]?.[Weekday.Monday];

Option 2: Handle a potential undefined value like this:

playground

enum Size {
  Small = 'small',
  Medium = 'medium',
  Large = 'large',
};

enum Weekday {
  Monday = 'Monday',
  Tuesday = 'Tuesday',
  Friday = 'Friday',
};

type MenuType = {};

const mapping: {
     [size in Size]?: { 
         [weekday in Weekday]? : MenuType;
     };
} = {
    [Size.Medium]: { 
        [Weekday.Tuesday]: {},
    },

    [Size.Large]: { 
        [Weekday.Monday]: {},
        [Weekday.Friday]: {},
    },
};

const menu = mapping[Size.Large]?.[Weekday.Monday];

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Attempting to connect to "http://localhost:4242/webhook" was unsuccessful due to a connection refusal when trying to dial tcp 127.0.0.1:4242

In my next.js 13 project, I am integrating stripe with TypeScript and configuring the app router. To create a stripe event in my local machine, I ran stripe listen --forward-to localhost:4242/webhook, but now I am encountered with the error message stripe ...

typescript add some flair to the setter function

I'm attempting to enhance a setter function within a class in the following manner: export class SearchResultSortBy{ private sortByChoice; constructor() { ...} /* getters & setters */ get sortBy() { return this.sortByCh ...

Tips on selecting an element with matching element attributes on a button that contains a span tag using Protractor in TypeScript

https://i.sstatic.net/LAhi8.jpg Seeking assistance with creating a protractor TypeScript code to click a button with _ngcontent and span class. Does anyone have any suggestions on how to achieve this? Here is the code snippet from the site: <form _ngc ...

Strategies for handling timeouts in TypeScript testing

When I attempt to use the calculator method to trigger the email() method, there seems to be an issue with the elements not rendering properly on the page. After waiting for a significant amount of time, a timeout error is thrown. Has anyone encountered th ...

This property cannot be found on the specified type

So, I have this TypeScript function that will return one of two different objects based on the input value: function myfunc(isError:boolean): {response:string}|{error:string} { if(isError) return {error:''} return {response:''} } N ...

Utilize Angular HttpClient to send a new Array created from fresh FormData to the server

I have an Array of Objects that contains files (images) with unique fields. When submitting, a new Array of Objects is sent to the server using Angular HttpClient. // Original Array of Objects let originalArray = [ { "name": & ...

Generating dynamically loaded components in Angular 2 with lazy loading

We are integrating an angular2 app into a cms (Sitecore) where content editors need the ability to add, remove, and rearrange components on a page, as well as include new components as needed. This is achieved by having the cms generate script tags to loa ...

Implementing dependency injection in TypeScript within AngularJS

I am currently in the process of transitioning a component (AngularJS 1.6) from JavaScript to TypeScript. class NewProjectCtrl { price: number; static $inject = ['$http']; constructor($http) { let ctrl = this; ctrl. ...

Incorporating interactive buttons within Leaflet popups

I'm facing an issue with adding buttons to a Leaflet popup that appears when clicking on the map. My goal is to have the popup display 2 buttons: Start from Here Go to this Location The desired outcome looks like this sketch: ___________________ ...

Typescript: Establishing a class method with parameters that are inherent to the class

After creating a class, I realized that there is repeated logic that can be extracted into a method on the class to be reused by other properties of the class. class Card { protected readonly data: Data; protected readonly user: User; nameVal: strin ...

The classification of rejected promises in Typescript

Is it possible to set the type of rejection for a promise? For example: const start = (): Promise<string> => { return new Promise((resolve, reject) => { if (someCondition) { resolve('correct!'); } else { ...

Mastering the Correct Usage of AuthGuard

I am facing an issue with implementing authguard in my angular application. I have set up a post request to my spring boot backend, and upon success, I set a value to true which I then check in my canActivate method of the authguard. However, for some reas ...

Zoom in and out on a WebGL canvas created using Three.js using the mouse scroll wheel

Currently delving into the world of WebGL (Three.js) to explore the possibilities of rendering 3D scenes within an Angular app. One challenge I'm facing is finding a way to make the mousewheel events zoom in and out of the canvas specifically, rather ...

Tips for utilizing ngIf based on the value of a variable

Here is the code from my file.html: <button ion-button item-right> <ion-icon name="md-add-circle" (click)="save();"></ion-icon> </button> The content of file.ts is: editmode = false; I am trying to achieve the foll ...

An email value being recognized as NULL

create-employee.html <div class="form-group"> <label for="exampleInputEmail1">Email address</label> <span><input type="text" [required]="!standingQueue" class="form-control" name="exampleInputEmail1" ...

Is it advisable to switch all properties to Angular Signals?

Recently, I've been utilizing signals to replace certain properties in my components that would typically require computed logic or be reactive to the effect hook. It got me thinking - should I be replacing all of my properties with signals, even if t ...

What is the process for retrieving the chosen country code using material-ui-phone-number?

When incorporating user input for phone numbers, I have opted to utilize a package titled material-ui-phone-number. However, the challenge arises when attempting to retrieve the country code to verify if the user has included a 0 after the code. This infor ...

Reusing Angular routes across different modules for backbutton functionality

Insights on my Application (Angular 12): Comprises of 3 Modules, each containing an overview page with a list and specific detail pages Each route is assigned an area tag to identify the user's navigation within the module Goal for Angular´s RouteR ...

Establishing the initial state within the constructor of a React Component utilizing a generic state

I have encountered an issue with React and Typescript. I am working on a component that utilizes two generics for props and state. interface Props { foo: string; } interface State { bar: string; } class Foo< P extends Props = Props, S e ...

The binding element 'params' is assumed to have a type of 'any' by default

I encountered an issue The binding element 'params' implicitly has an 'any' type. Below is the code snippet in question: export default function Page({ params }) { const { slug } = params; return ( <> <h1>{s ...