Ensuring Map Safety in Typescript

Imagine having a Map structure like the one found in file CategoryMap.ts

export default new Map<number, SubCategory[]>([
   [11, [100, 101]],
   [12, [102, 103]],
   ...
])

Is there a way to create a type guard for this Map?

import categoryMap from 'CategoryMap'

type CategoryMapId = keyof typeof categoryMap

function isCategoryId(id: number): id is CategoryMapId {
   return categoryMap.has(id)
}

The issue here is that CategoryMapId appears as

"[Symbol.toStringTag]" | "clear" | "delete" | "forEach" | "get" | "has" | "set" | "size" | "[Symbol.iterator]" | "entries" | "keys" | ...

What I would like is for the type CategoryMapId to be 11 | 12 ...

Any ideas on how to solve this? Thanks.

Answer №1

To designate a type for the 'key' of the map, you can do the following:

const exampleMap = new Map<11 | 12, [number, number]>([
  [11, [100, 101]],
  [12, [102, 103]],
]);

const y = exampleMap.get(11); // works
const x = exampleMap.get(13); // type error

If you wish TypeScript to infer this at runtime, there is a workaround suggested in this response:

type KeyOfCustomMap<M extends Map<unknown, unknown>> = M extends Map<infer K, unknown> ? K : never

const customMap = new Map<number, [number, number]>([
  [11, [100, 101]],
  [12, [102, 103]],
]);

type CustomMapKey = KeyOfCustomMap<typeof customMap>;

const isCustomKeyId = (id: number): id is CustomMapKey =>
  customMap.has(id);

In this scenario, CustomMapKey is still assigned the type number, which may not be ideal.

If you opt for using an object instead of a Map, it allows for obtaining proper key types:

const newObjMap = {
  11: [100, 101],
  12: [102, 103],
}
type CustomMapKey = keyof typeof newObjMap;

const isCustomKeyId = (id: number): id is CustomMapKey =>
  Object.keys(newObjMap).map(Number).indexOf(id) > -1;

const x = isCustomKeyId(11); // true
const y = isCustomKeyId(13); // false

const getValue = (id: number) => {
  if (isCustomKeyId(id)) {
    return newObjMap[id];
  } else {
    return [];
  }
}

This approach might not align with your specific requirements, as it appears challenging to achieve with Maps currently.

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

Accessing form data within Mongoose schema hooks via JavaScript

I have a form where I've split the content into two separate MongoDB schemas. I want to access variables that are within node.js/express.js directly in mongoose schema hooks, whether through pre or post hooks of the schema. Here are my files: expres ...

Should objects passed as props be modified in Vue.js components?

I've observed that in Vue, object fields passed as Props can be changed, and these changes reflect in the parent component. Is this considered a bad practice? Should it be avoided, or is it acceptable to use? What are the potential pitfalls of this a ...

Methods for adding a line to an array

I am currently working on a loop where I need to populate my array called photos: $scope.photos = []; var str = data.data.Photos; var res = str.split('|'); angular.forEach(res, function (item) { ...

Checking validation with parsley.js without triggering form submission

I have been working with the latest release of Parsley for data validation. While it is validating my data correctly, I am encountering an issue where the form does not submit after validation is complete. I have spent hours trying to troubleshoot this pro ...

What is the best way to initiate a Bootstrap carousel so that it begins with the first image every time a modal window appears

I am in the process of creating my own portfolio to showcase my work. I have implemented a feature where clicking on an image opens up a Bootstrap carousel. However, I'm facing an issue where the carousel doesn't always start with the first imag ...

Navigate between pictures using hover in jQuery

I am working on creating a feature where images cycle through individually every 2 seconds, but switch to the right image when its associated link is hovered. So far, I have managed to make the images show up on hover, but I am struggling with getting them ...

Having trouble with collision detection in Three.js?

I am currently working on creating a 3D Breakout game using three.js. Most of the collision detection for the walls is already implemented, but I'm facing difficulties with the collision against the paddle. Below is my code snippet: // A 3D breakout ...

Using JQUERY to execute a callback function after an AJAX request is completed

I encountered a situation where I have the following code snippet: <a onclick="$('.element').hide(0); doMyMethod(_element = $(this));"></a> The doMyMethod() function is actually an ajax request. What I am trying to accomplish is to ...

Customize the appearance of disabled dates in the eonasdan-datetimepicker styling

I am seeking to customize the default styles for the "eonasdan-datetimepicker" (https://github.com/Eonasdan/bootstrap-datetimepicker) by implementing a basic hover message feature. The CSS attributes currently applied to disabled dates are as follows: .bo ...

Using the map function with a React onClick handler

After tirelessly scouring the internet for answers to my query, I've hit a dead end. My goal is to implement a basic react click handler on my button, but for some reason, it just won't cooperate. It's likely something incredibly straightfor ...

The ng-repeat function is failing to show any data on the HTML view, instead only displaying a row for each property present

HTML Code: <div ng-repeat="addr in addrShipData"> <input type="radio" name="resp1" ng-checked='true'/> {{addr.addressLine1 +","+addr.addressLine2+", "+addr.city+ ","+addr.state+", "+addr.country+", "+addr.zipCode+","+addr ...

Utilizing Angular 2 for a dynamic Google Map experience with numerous markers

I am currently working on an Angular2 project that involves integrating Google Maps. My goal is to display multiple markers around a specific area on the map. Although I have been able to get the map running, I am facing issues with displaying the markers ...

The responseText array is encountering parsing issues

Utilizing ajax, I am retrieving a json_encoded array from my PHP parser. The responseText returned is ["4.wav","2.wav","3.wav","6.mp3","1.mp3","5.wav"] If I place this into an array like so: var myArray = ["4.wav","2.wav","3.wav","6.mp3","1.mp3","5.wav" ...

React is running smoothly, however, when attempting to call the React flow, an error is encountered: "Error: (0 , react__WEBPACK_IMPORTED_MODULE_0__.createContext) is not

Recently, I set up a React application using Next.js and TypeScript. Initially, everything was running smoothly with the command npm run dev. However, upon integrating the react flow library with npm install reactflow, I encountered an error when trying to ...

Using AJAX and PHP to dynamically fill HTML drop-down menus

In order to populate the DropDown controls on my HTML Form dynamically, I have implemented a code that utilizes AJAX to make a call to a .php file. This .php file is responsible for filling the DropDown control with values from a single column. Throughout ...

Deactivate JQuery star rating plugin after user has voted

I've integrated the JQuery star rating plugin (v2.61) from into my project. Everything is working smoothly, but I am looking for a way to disable the stars once a user has voted. Currently, users are able to select their rating and submit it through ...

After successfully executing an AJAX request three times, it encountered a failure

I have implemented a script to send instant messages to my database asynchronously. Here is the code: function sendMessage(content, thread_id, ghost_id) { var url = "ajax_submit_message.php"; var data = { content: content, thread_id: thread_id }; ...

What is the best way to turn each function within the module pattern into a promise?

Utilizing Angular 1.5, I have developed a factory function that returns a literal object structured as follows: return { item: null, get: function() { return item; }, create: function() { if (this.get()){ this.remove(); ...

How selection.join behaves when every node contains child elements

I have been following the amazing tutorial on to learn more about the join paradigm. Everything was working fine until I tried to make each node more complex by adding a group with text inside. The main group gets updated, but the child one does not. Sn ...

Adjusting the opacity of the background image in the section - focus solely on the background

This section is what I'm working on. <section ID="Cover"> <div id="searchEngine">hello</div> </section> I am trying to achieve a fade in/out effect specifically for the background image of the Cover section. T ...