Using an alias to strip the readonly modifier in Typescript

It appears that in typescript, it is possible to remove the readonly modifier from a type through a simple assignment:

function updateValue(x: { readonly content: string }) {
    x.content = "new content"; // This operation would normally fail
    modifyContent(x); // Surprisingly, this works without any issues
}

function modifyContent(x: { content: string }) {
    x.content = "new content";
}

Is there a risk of accidentally mutating a readonly field with this approach? Have I misunderstood the proper usage of the readonly keyword in typescript? Are there stricter alternatives available in typescript to prevent such unauthorized modifications?

UPDATE: Acknowledging the existing behavior, here's a workaround that may be helpful in certain scenarios, although not foolproof:

type Immutable<T> = { __mutable: true } & { [P in keyof T]: T[P] };
type Readonly<T> = T extends Immutable<any> ? { readonly [P in Exclude<keyof T, "__mutable">]: T[P] } : never;

type SomeType = Immutable<{
    content: string;
}>;

function updateContent(x: Readonly<SomeType>) {
    let y: SomeType = x; // This will trigger a compile-time error
    y.content = "new content";
}

Answer №1

The issue at hand has been well-documented and acknowledged here. The fundamental problem lies in the fact that the readonly modifier does not affect assignability, reducing its overall utility.

Currently, there is no known method to enforce stricter rules in this situation. No compiler options or clever type manipulations exist to address this limitation. It seems unlikely that a solution will emerge soon due to the inherent constraints within the type system regarding the presence of readonly on types.

Important: This discussion took place during the reign of Typescript 3.1; future iterations may bring about changes that challenge these conclusions.

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

How to use multiple template urls in Angular 6

Currently, I am creating a front-end using Angular 6 and facing the challenge of having components with varying html structures based on the user who is logged in. The number of templates required can range from 2 to over 20, so my preference would be to ...

Required file missing in React application unable to locate

I have a project organized in the following way: - my-app - src - some files - public - index.html - ... When I run npm start, the application functions as expected. Now, I am looking to rename src to application! After renami ...

Blending TypeScript declaration files and Node.js require across various files within an internal module

Is it problematic to mix Node.js modules (require) with TypeScript definition files (d.ts) multiple times within a module? In my case, I organize my modules into namespaces per folder similar to how it's done in C#. After compiling them all using tsc ...

One-Of-A-Kind Typescript Singleton Featuring the Execute Method

Is it feasible to create a singleton or regular instance that requires calling a specific method? For instance: logger.instance().setup({ logs: true }); OR new logger(); logger.setup({ logs: true }); If attempting to call the logger without chaining the ...

Import reactjs modules without the need for Browserify, Webpack, or Babel

I am attempting to set up a TypeScript HTML application in Visual Studio. My goal is to incorporate reactjs v0.14.7 without relying on tools like Browserify. But, how can I utilize the react-dom module in this scenario? Let's set aside TypeScript fo ...

IntersectionObserver activates prior to element's entrance into the viewport

I've set up a Vue component with the following structure: <template> <article> <!-- This content spans several viewport heights: you *have* to scroll to get to the bottom --> {{ content }} </article> <span ref ...

Menu Navigation: Sequentially Colored Badges for Navigation Items

Within the MainService.ts file, there is a function that can alter the color set in badgesColorSet. The json config already defines 3 colors and the goal is for these colors to change each time the website is refreshed - for example, changing from red to g ...

Error: Jest + Typescript does not recognize the "describe" function

When setting up Jest with ts-jest, I encountered the error "ReferenceError: describe is not defined" during runtime. Check out this minimal example for more information: https://github.com/PFight/jest-ts-describe-not-defined-problem I'm not sure what ...

Does a typescript definition file exist for Apple MapKit JS?

Before embarking on creating one, I'm curious if anyone has come across a typescript definition file (.d.ts) for Apple MapKit JS? ...

Can you provide input to the reducer function?

In the creator, an action is defined like this: export const actionCreators = { submitlink: (url: string) => <SubmitLinkAction>{ type: 'SUBMIT_LINK' } } In the component that calls it: public render() { return <div> ...

Issue with accessing custom method in subclass in Typescript

Recently delving into TypeScript, I decided to subclass Error and add a new method called getCode() in my MyError class. export class MyError extends Error { public code: number; constructor(code: number, message?: string) { super(mes ...

Unable to associate a model with an additional attribute in objection because of a TypeScript issue

I'm attempting to establish a connection between two models while adding an additional property called "url": if (typeof session.id === "number") { const sessionUser = await Session.relatedQuery("users") .for(session.id) .relate({ id: ...

Why does Material-UI's "withStyles()" not function properly with a specified constructor in Typescript?

Update: Please note that there was an issue with the constructor generated by IntelliJ IDEA, but it has been fixed. You can find more details here: I'm exploring the use of Material-UI in my application, and I've encountered some challenges wit ...

Struggling with "Content" not being recognized in Typescript PouchDB transpilation errors?

I have been diligently working on an Ionic app for the past three months with no major issues during development or deployment to mobile devices. However, yesterday I encountered a frustrating NPM dependency problem while trying to deploy to mobile. In an ...

Having issues with Craco not recognizing alias configuration for TypeScript in Azure Pipeline webpack

I am encountering an issue with my ReactJs app that uses Craco, Webpack, and Typescript. While the application can run and build successfully locally, I am facing problems when trying to build it on Azure DevOps, specifically in creating aliases. azure ...

Having trouble with importing rxjs operators

After updating the imports for rxjs operators in my project to follow the new recommended syntax, I encountered an issue with the "do" operator. While switchMap and debounceTime were updated successfully like this: import { switchMap, debounceTime } ...

An error is anticipated when () is added, but surprisingly, I still encounter an error as well. This issue arises in React-Native and Typescript

I am still relatively new to React-Native, but I have been using React-Native, TypeScript, and integrating it with Firebase. An unusual error has occurred, which is visible in the screenshot below. However, when checking in VSC, the error seems to be non-e ...

Tips on identifying and handling errors without the need for type assertions in this code segment

My code is correct, but it's becoming difficult to maintain... interface FuncContainer<F extends (..._: Array<any>) => any> { func: F args: Parameters<F> } const func: FuncContainer<typeof Math.min> = { func: Math.min ...

Obtaining a list of dates for a particular week using React DayPicker

I'm seeking the ability to click on a specific week number within the react DayPicker and receive an array of all dates within that week. The DayPicker package I am using can be found here: I've copied the example code from react DayPicker to e ...

What is the best way to have an icon appear when a child component div is clicked, without it displaying on other similar divs?

Within my child component div, I have configured it to display information from an object located in the parent component. Initially, when the web app loads, it correctly shows three divs with names and messages retrieved from the created object. However, ...