Is it possible to use Date as a key in a Typescript Map?

Within my application, I have a requirement for mapping objects according to specific dates. Given that typescript provides both the Map and Date objects, I initially assumed this task would be straightforward.

  let map: Map<Date, MyObject> = new Map<Date, MyObject>();

I thought I could simply utilize the set method to insert new key-value pairs. However, upon implementation, I discovered that retrieving values using date keys required the exact same instance of Date.

To verify this behavior, I wrote a unit test:

  it('Experiencing an Issue', () => {
      let d1: Date = new Date(2019, 11, 25);    // Christmas day
      let d2: Date = new Date(2019, 11, 25);    // The same Christmas day?

      let m: Map<Date, string> = new Map<Date, string>();
      m.set(d1, "X");

      expect(m.get(d1)).toBe("X");   // <- This works fine.
      expect(m.get(d2)).toBe("X");   // <- This test fails.
  });

This raises the question, why is it necessary to use the precise same instance in order to retrieve a value from the map?

Answer №1

The reason it will always be falsy is because each of the date objects being compared are unique mutable javascript objects.

For example,

new Date(2020, 5, 10) === new Date(2020, 5, 10) ==> false
.

If you want to learn more about this topic, check out this helpful post.

Answer №2

In the realm of programming, the core logic of a Map revolves around storing values in key-value pairs.

When it comes to comparing keys, they must always be of the same reference. In many programming languages, string literal references are considered equal, making strings a preferred choice as keys in maps.

This behavior extends beyond just date objects and applies to any other mutable object type.

For example:

let str1 = 'test';
let str2 = 'test';
str1 == str2; // true

let str1 = new String('test');
let str2 = new String('test');
str1 == str2; // false

When retrieving a value from a map, the actual data of the keys is not important. What matters is the unique identity of the key being searched for. Immutable objects may contain the same data, but if their references are different, they will be treated as separate keys.

To ensure consistency throughout your program, opt for types that maintain the same references, like string literals.

Consider one more example:

class Demo {
  field: string;
  constructor(f: string) {
    this.field = f;
  }
}

const d1 = new Demo('test');
const d2 = new Demo('test');

// Both objects appear identical in terms of data, but their references differ.
// Therefore, they will be treated as distinct keys.
const m: Map<any, string> = new Map<any, string>();
m.set(d1, 'value1');

console.log(m.get(d1)); // value1
console.log(m.get(d2)); // undefined

Answer №3

It's recommended to use primitive values like numbers or strings as keys in a Map:

let myMap: Map<string, string> = new Map<string, string>();

let date1: Date = new Date(2019, 11, 25);    // Christmas day
let date2: Date = new Date(2019, 11, 25);    // Same Christmas day?

myMap.set(date1.toDateString(), "X");

console.log(date1.toDateString())
console.log(date2.toDateString())
console.log(myMap.get(date2.toDateString()))

You can find more information about this behavior in the comments above.

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

Error: Unable to use import statement outside of a module when deploying Firebase with TypeScript

Every time I try to run firebase deploy, an error pops up while parsing my function triggers. It specifically points to this line of code: import * as functions from 'firebase-functions'; at the beginning of my file. This is a new problem for me ...

Discover the power of merging multiple events in RxJS for efficient data retrieval and filtering

In various scenarios, I need to display a table of data with additional functionality for filtering and refreshing. The table is accompanied by two input fields - one for local filtering (searchLocal) and another for backend filtering (searchBackend). Ther ...

encountering the issue of not being able to assign a parameter of type 'string | undefined' to a parameter of type

Seeking help with the following issue: "Argument of type 'string | undefined' is not assignable to parameter of type" I am unsure how to resolve this error. Here is the section of code where it occurs: export interface IDropDown { l ...

Issues arise when Typescript fails to convert an image URL into a base64 encoded string

My current challenge involves converting an image to base 64 format using its URL. This is the method I am currently using: convertToBase64(img) { var canvas = document.createElement("canvas"); canvas.width = img.width; canvas.height = img.he ...

The module './login/servcioprueba1.service' is missing the exported member 'prueba'. Kindly add this member to resolve the issue

I am working on an Angular 8 project that involves a service file. To generate the service, I used the command: ng g s servicioprueba1 After generating the service, I imported it into my code as shown below. Included in Block 2 is the line where I impor ...

Formatting decimals with dots in Angular using the decimal pipe

When using the Angular(4) decimal pipe, I noticed that dots are shown with numbers that have more than 4 digits. However, when the number has exactly 4 digits, the dot is not displayed. For example: <td>USD {{amount| number: '1.2-2'}} < ...

What is the best way to modify onClick events for elements in Ionic v4 with React?

Is there a way for me to interact with a button or IonItemSliding in order to alter the text or color of an element? <IonItemOptions side="start"> <IonItemOption color="success">Yes</I ...

Transfer the current Angular project to operate as a separate entity

After successfully migrating my Angular project from version 13 to version 16 step by step, I am now aiming to make it fully standalone before proceeding with the migration to version 17. I am wondering if there is a utility available that can assist me i ...

Tips for enhancing a TypeScript interface for a React component in (Material-UI) by utilizing styled-components

I've been struggling to find a solution for this overload issue with no luck so far. My stack includes Typescript, Styled-components, and Material-UI. I am utilizing styled(MUIButton) to extend the default Button from MUI. While my props are being pas ...

Passing along the mouse event to the containing canvas element that utilizes chart.js

Recently, I created a custom tooltip for my chart.js chart by implementing a div that moves above the chart. While it works well, I noticed that the tooltip is capturing mouse events rather than propagating them to the parent element (the chart) for updati ...

Ensure that the hook component has completed updating before providing the value to the form

Lately, I've encountered an issue that's been bothering me. I'm trying to set up a simple panel for adding new articles or news to my app using Firebase. To achieve this, I created a custom hook to fetch the highest current article ID, which ...

Issue with Bootstrap Angular dropdown menu malfunctioning within ChildRoute

Recently, I have been working on integrating admin bootstrap html with Angular. As part of this integration, I added CSS and JS files in angular.json as shown below: "styles": [ "src/styles.css", "src/assets/goo ...

The validation requirement in Angular prevents the form from being considered valid until the input has been modified

I have included the HTML5 required property in the below HTML code: <div class="col-sm-3"> <label>{{question.placeholder}}<span *ngIf="question.required">*</span></label> </div> <d ...

How can you utilize Angular 2 Services for sharing global variables?

Within our NG starter boilerplate, the file app.component.ts contains the following code: export class AppComponent {title = "Website Title"} The title variable will be displayed in the appropriate app.component.html as shown below: <p>{{title}}&l ...

Mapping a TypeScript tuple into a new tuple by leveraging Array.map

I attempted to transform a TypeScript tuple into another tuple using Array.map in the following manner: const tuple1: [number, number, number] = [1, 2, 3]; const tuple2: [number, number, number] = tuple1.map(x => x * 2); console.log(tuple2); TypeScript ...

An error persists in PhpStorm inspection regarding the absence of AppComponent declaration in an Angular module

After creating a new Angular application, I am encountering the issue of getting the error message "X is not declared in any Angular module" on every component, including the automatically generated AppComponent. Despite having the latest version of the An ...

Issue reported: "Usage of variable 'someVar' before assignment" ; however, it is being properly assigned before usage

This piece of code showcases the issue: let someVar: number; const someFunc = async () => { someVar = 1; } await someFunc(); if (someVar == 1) { console.log('It is 1'); } As a result, you will encounter ...

Can anyone guide me on creating a dictionary of origin-destination pairs using a distance matrix in Python?

I have an Excel workbook with a flow matrix that indicates the cargo movement between two points. Here's an example: 1 2 3 ... n 1 0 7 8 2 5 0 3 . 3 6 9 0 . . . . . ... . . . n 0 I am trying to generate a ...

Alphabetically sorting objects in an array using Angular

If your TypeScript code looks something like this: items: { size: number, name: string }[] = []; ngOnInit(): void { this.items = [ { size: 3, name: 'Richard' }, { size: 17, name: 'Alex' }, ...

Eliminate Angular Firebase Object and Storage

Currently in the final stages of completing my initial project using Angular and Firebase. I have encountered a query regarding the deletion of objects utilizing both technologies. My service is designed to delete an object that contains a nested object n ...