What is the proper way to transform an Immutable Map into a strictly typed object in Typescript?

Is there a way to translate this code snippet from JavaScript to TypeScript?

const myMap = Immutable.Map({
   item1: null,
   item2: "hello",
   item3: Immutable.Map({
     item4: 2,
     item5: true
   })
});

Answer №1

Although I haven't used the immutable.js framework before, I would recommend utilizing a standard JavaScript map instead. In Typescript, you can make use of the ReadonlyMap type which eliminates all setters from the map object. While the object won't be truly immutable (meaning no runtime error), the Typescript compiler will raise an error if you attempt to modify the values.

const myMap: ReadonlyMap<string, string> = new Map([
    ['item1', 'foo'],
    ['item2', 'bar']
]);

console.log(myMap.get('item1')); // output will be foo

myMap.set('item1', 'foobar'); // Error: Property set does not exist on type readonly map

Slightly unrelated, but I believe reconsidering your map structure might be beneficial. Using string | null is acceptable, but employing

string | null | ReadonlyMap<string, number | boolean>
seems like an unusual choice for a map.

For more information, you can refer to the map documentation provided by Mozilla.

Answer №2

A possible solution could be:

type MakeImmutable<T> = {
  readonly [Key in keyof T]: MakeImmutable<T[Key]>;
};

// Defining the Person interface
interface Person {
  name: string;
  lastName: string;
  address: {
    street: string;
    zipCode: number;
  }
}

const person: MakeImmutable<Person> = {
  name: 'john',
  lastName: 'doe',
  address: {
    street: 'main street',
    zipCode: 12345
  }
}

// Trying to mutate should result in a TypeScript error for read-only properties
person.name = 'jane';
person.address.street = 'new street'

Special thanks to the original author mentioned in this article: https://www.example.com/immutable-typescript-solution

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

Steps for initiating an Angular 4 project

While most developers have moved on to Angular 5, I was tasked with creating a project using Angular 4. After conducting research for several days, I discovered that downgrading the Angular CLI would allow me to accomplish this. By following this approach, ...

Tips for determining the datatype of a callback parameter based on the specified event name

Let's say we have the following code snippet: type eventType = "ready" | "buzz"; type eventTypeReadyInput = {appIsReady: string}; interface mysdk { on:(event: eventType, cb: (input: eventTypeCallbackInput) => void) => void } mysdk.on("ready", ...

How can you specify a tuple type in TypeScript for an array that is empty?

I'm attempting to convert a const object into a class in order to create readonly properties. The goal is to ensure that the values in these properties never change. Specifically, I'm trying to create a module property in my class that is define ...

Determine the data type based on the object property

Can a versatile function be created to automatically determine the type based on an "external" object property? Consider the following scenario: const resolversMap: { overallRankingPlacement: (issuer: number, args: Record<string, any>, context: Re ...

Watching - transforming / combining

I am a beginner when it comes to working with Observables. Here's the Effect that I am using: My goal is to dispatch the PositionUpdateAction or PositionFailedAction before the SunriseSunsetAction is dispatched. Currently, what happens is that the r ...

Creating and managing global context with useReducer in TypeScript and React

One issue that I am facing is with the route containing a login and logout button, where the browser error states 'Property 'dispatch' does not exist on type '{}'. (home.tsx) import React, { useContext, useEffect, useRef, use ...

Showing elapsed time similar to YouTube in an Angular 8 application

Currently, I am developing an Angular application to replicate certain features found on YouTube by utilizing data fetched from an API. This API provides video timestamps in a string format Each timestamp follows this structure : YYYY-MM-DDTHH:MM:SS For ...

Prioritizing TypeScript React props in VS Code IntelliSense for enhanced development

Imagine having this efficient component that works perfectly: import clsx from "clsx"; import React from "react"; interface HeadingProps extends React.DetailedHTMLProps< React.HTMLAttributes<HTMLDivElement>, ...

Craft a unique typings file tailored to your needs

After recently creating my first published npm package named "Foo", I encountered some difficulties while trying to consume it in a TypeScript project. The tutorials on how to declare modules with custom typings were not clear enough for me. Here are the k ...

AngluarFire 2 authState function displaying null after refreshing the page

Currently, I am working on integrating Firebase with AngularFire 2 and facing an issue. The problem arises when I try to refresh the page, as the auth instance returns null. Below is the code snippet for my AuthService: Everything functions correctly, b ...

Trouble with a third-party library component not functioning properly on the server side in a Next.js environment

I've encountered a puzzling issue lately in my work. Recently, I started using the new NextJS v13 with React server components. I'm integrating it into a project that depends on a small private third-party library I created and shared among mul ...

Excessive wait times during the construction of a moderately sized application (over 2 minutes) using TypeScript and loaders like Vue-Loader and TS-Loader

I'm currently utilizing Nuxt 2 with TypeScript and the most up-to-date dependency versions available. Even though my app is of medium size, the compilation time seems excessively slow. Here are my PC specs: Ryzen 7 2700X (8 Cores/16 Threads) 16 GB D ...

Expanding the StringConstructor in TypeScript results in a function that is not defined

I'm currently trying to enhance the String class in TypeScript 2.5 by adding a static method, which will be compiled to ES5. Here's what I have in StringExtensions.d.ts: declare interface StringConstructor { isNullOrEmpty(value: string | nu ...

Tips for binding to a single input box within an ngFor loop

Can anyone lend a hand with some code? I'm working on a straightforward table using ngFor, but I'm facing an issue with input binding. The problem is that all the input fields generated by ngFor display the same value when typing. How can I preve ...

Struggling to access the production API results in a frustrating 404 error

I'm currently facing an issue with deploying my website as the API call is not functioning properly. Specifically, I am receiving a 404 not found error message. Here is the structure of my project: . After running npm run build, this is how my nex ...

Manage numerous receiving bank accounts, allowing customers to transfer money to each specific account

Managing multiple receiving bank accounts and enabling customers to transfer money to specific accounts is a key requirement in my application. Can Plaid help me achieve this functionality? Could you provide guidance on how to implement this feature using ...

Ensuring accurate date formatting of API responses in TypeScript

My REST API returns data in the format shown below:- {"id": 1, "name": "New event", "date": "2020-11-14T18:02:00"} In my React frontend app, I have an interface like this:- export interface MyEvent { id ...

An error occurred within Angular 8 while attempting an HTTP post request, as it was unable to access the 'message' property of

After conducting a search on Stack Overflow, I found a similar question that relates to my issue. Login OTP Component: onSubmitValidOTP() { this.authenticationService.ValidOTP(this.fo.OtpControl.value, username, role) .pipe(first ...

What could be the reason for the TypeScript compiler not recognizing tsconfig.json?

I recently came across a file from a tutorial that has left me confused due to the inconsistency between documentation, tutorials, and examples: /scripts/tsconfig.json: { "compilerOptions": { "emitDecoratorMetadata": true, "experiment ...

When utilizing the Angular 2 Stack, the Typescript Reflect.getMetadata('design:type'...) method may return an Object instead of a Date

When running the code sample below, it outputs "[Function: Date]", which is as expected. import 'reflect-metadata' function logType(target : any, key : string) { var t = Reflect.getMetadata("design:type", target, key); console.log(`${k ...