Understanding TypeScript - Changing immutability and reversing Readonly<T>

Let's consider a scenario where I have the following mutable class:

class Foo {
    constructor(public bar: any) { }
}

I am able to create instances of this class with readonly properties like this:

const foo: Readonly<Foo> = new Foo(123);
foo.bar = 456; // error, cannot change the value of bar because it is readonly.

What if I want to do the opposite, where the class itself is immutable?

class Foo {
    constructor(public readonly bar: any) { }
}

Then, can I create mutable versions of this class like so:

const foo: Mutable<Foo> = new Foo(123);
foo.bar = 456;

Is there a way to achieve this?

Answer №1

Absolutely, utilizing -readonly in a type definition is completely acceptable.

type Mutable<T> = {
  -readonly [P in keyof T]: T[P];
};

const foo: Mutable<Foo> = new Foo(123);
foo.bar = 456;

Explore Here

Remember, it's vital to note that this alteration only applies to the type definition and does not impact the original logic.

type Mutable<T> = {
  -readonly [P in keyof T]: T[P];
};

class Foo {
    get test(): boolean {
      return true;
    }

    constructor(public readonly bar: any) { }
}

const foo: Mutable<Foo> = new Foo(123);
foo.bar = 456;
foo.test = false; // Caution: This will result in an error.

Answer №2

Here's a small tweak to the original solution that allows you to bypass the nested readonly definitions:

interface Mutable<T> {
  -readonly [P in keyof T]: Mutable<T[P]>;
}

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

Interpret information in Angular 2 using Typescript

Just starting with Angular (IONIC) and need help. How can I extract the userId or id from this code? his.response = data. //Looking for guidance on accessing Json keys Response : { "userId": 1, "id": 1, "title": "sunt aut facere repellat providen ...

The concept of Typescript involves taking a particular type and generating a union type within a generic interface

Picture a straightforward CollectionStore that contains methods for creating and updating a record. The create() method takes in a set of attributes and returns the same set with an added id property. On the other hand, the update method requires the set t ...

Having trouble with moving a range selector using Cypress code?

I am currently working on a cypress code that is meant to move the range selector from one location to another. While the range selector position is being selected correctly, it fails to actually move the range selector as intended. Below is the command f ...

Obtaining results from several observable requests within a function

A function is currently operational, functioning by setting a value in the component when called (user.userImage). getLoggedInUserPhoto() { this.adalService.acquireToken('https://graph.microsoft.com') .subscribe(token => { let header = ...

Angular error TS2339: The property 'before' is not found on type 'HTMLElement' / 'HTMLTextAreaElement' / etc

Objective: My goal is to reposition a div (containing a mat-select dropdown) ABOVE a mat-card-title when the user is accessing the site from a mobile device. If the user is not on a mobile device, the div should remain in its original position to the right ...

Angular: Generating a fresh instance of an object monthly

My goal is to create an object called "Activity" in Angular 8, which will automatically generate an activity for each month upon creation. For example: export class Activity { activityID = string; activityName = string; startDate = Date ...

What is the reason for the component property being valued within the subscribe body when it is not defined outside of it?

I am currently facing an issue with retrieving data from a SQL server table using http.get within the constructor of an Angular component 5. While I am able to assign the retrieved data to a component property inside the subscribe method, the value becomes ...

Whenever I try to update my list of products, I encounter an error message stating that the property 'title' cannot be read because it is null

I am encountering an issue with editing data stored in the database. When attempting to edit the data, it is not displaying correctly and I am receiving a "cannot read property" error. HTML admin-products.component.html <p> <a routerLink="/ad ...

What is the process of converting a union type into a union of arrays in TypeScript?

I have a Foo type that consists of multiple types For example: type Foo = string | number I need to receive this type and convert it into an array of the individual types within the union type TransformedFoo = ToUnionOfArray<Foo> // => string[] ...

Update the js file by incorporating the import statement

Currently, I am in the process of transitioning to using imports instead of requires for modules. Here is an example of my previous code: const { NETWORK } = require(`${basePath}/constants/network.js`); The content of network.js file is as follows: export ...

Developing a node module that includes nested subfolders

I'm currently working on an npm module and have the following index.ts file: export * from './src/A/index'; Right now, when importing in my app, it looks like this: import {something} from 'myModule'; Now, I want to enhance my ...

What is the process for defining the type or interface of an object in Visual Studio Code?

Is there a way to create a new type or interface by replicating the structure of a complex object that is imported from a library? For instance, in the image below, the object Text is taken from react-three/drei. https://i.sstatic.net/BcUzd.png Upon inspe ...

Leverage JSON files for pagination in NextJS

I am currently developing a science website where the post URLs are stored in a static JSON file. ScienceTopics.json- [ { "Subject": "Mathematics", "chapters": "mathematics", "contentList": [ ...

Angular JSON converter - Transform XML data to JSON format

Struggling to convert XML API response to JSON using xml2js library, facing issues with getting 'undefined' in the console. Here is my API service: export class WordgameService { public apiUrl = "http://www.wordgamedictionary.com/api/v1/reference ...

There was a Runtime Error that occurred, stating a TypeError: It is not possible to access properties of an undefined value (specifically

I've encountered an issue with a donut chart implemented from react-apex charts. Every time I try to render the page containing the chart, an error occurs. However, if I make changes to a property of the chart, it renders without any errors on the fro ...

The base class is invoking a function from its child class

There are two classes, a base class and a derived one, each with an init function. When constructing the derived class, it should: Call its base constructor which: 1.1. Calls its init function Call its own (derived) init function. The issue is that ...

Exploring the application of keyof with object structures instead of defined types

Looking to create a new type based on the keys of another object in TypeScript. Successfully achieved this through type inference. However, using an explicit type Record<string, something> results in keyof returning string instead of a union of the ...

Modules failing to load in the System JS framework

Encountering a puzzling issue with System JS while experimenting with Angular 2. Initially, everything runs smoothly, but at random times, System JS struggles to locate modules... An error message pops up: GET http://localhost:9000/angular2/platform/bro ...

What is the technique for accessing the original function within a class using a proxy?

I attempted to monkey patch a function within my class using Proxy. Is there a way to access and execute the original function? class foo { x = 10; bar() { console.log({ x: this.x }); } } foo.prototype.bar = new Proxy(foo.prototype.bar, { ap ...

Utilizing Highcharts with React and Typescript for Event Typing

Implementing Highcharts Events in TypeScript I have integrated custom events into my Highcharts using the React wrapper. One example is to toggle the legend when entering and exiting full screen mode. const options: Highcharts.Options = { chart: { e ...