Cannot assign to read only property of object
  • 14-May-2023
Lightrun Team
Author Lightrun Team
Share
Cannot assign to read only property of object

Cannot assign to read only property of object

Lightrun Team
Lightrun Team
14-May-2023

Explanation of the problem

The following error is encountered: “Cannot assign to read-only property ‘name’ of object ‘#<Category>'” when attempting to assign values to non-initialized properties decorated with decorators. The code utilizes the “typeorm” library, and defines a class called “Category” which is decorated with the “Entity” decorator. Within the class, there are two properties decorated with the “PrimaryColumn” and “Column” decorators respectively, namely “id” and “name”.

 

Troubleshooting with the Lightrun Developer Observability Platform

Getting a sense of what’s actually happening inside a live application is a frustrating experience, one that relies mostly on querying and observing whatever logs were written during development.
Lightrun is a Developer Observability Platform, allowing developers to add telemetry to live applications in real-time, on-demand, and right from the IDE.

  • Instantly add logs to, set metrics in, and take snapshots of live applications
  • Insights delivered straight to your IDE or CLI
  • Works where you do: dev, QA, staging, CI/CD, and production

Start for free today

Problem solution for: Cannot assign to read only property of object

To resolve the issue, the properties can be initialized with default values. Specifically, the “id” property can be initialized to “undefined”, and the “name” property can be initialized to an empty string. The modified code block is shown below:

import {Entity, PrimaryColumn, Column} from "typeorm";

@Entity()
export class Category {

    @PrimaryColumn("int", { generated: true })
    id = undefined;

    @Column("string")
    name = "";

}

It is worth noting that the above solution may not be the most elegant, as initializing the properties with default values can be considered as ugly. One possible reason for this is that the descriptor is not made writable. Therefore, there may exist alternative solutions to this problem that achieve the same result in a more elegant way.

One alternative solution to the problem of initializing non-initialized properties decorated with decorators is to use TypeScript’s “constructor parameter property” feature. This feature allows a constructor parameter to automatically become a class property with the same name, and can also be decorated with a decorator.

Using this feature, the Category class can be modified to look like this:

 

import {Entity, PrimaryColumn, Column} from "typeorm";

@Entity()
export class Category {
    constructor(
        @PrimaryColumn("int", { generated: true }) public id: number,
        @Column("string") public name: string,
    ) {}
}

In the modified version of the class, the constructor takes in two parameters, “id” and “name”, which are automatically assigned as class properties. These parameters are also decorated with the “PrimaryColumn” and “Column” decorators respectively.

This approach is more concise and avoids the need to initialize the properties with default values. Additionally, it makes the code more readable and less cluttered. However, it should be noted that this approach may not be feasible in all situations, especially if the class has many properties or if the properties have complex initialization logic.

Other popular problems with babel-plugin-transform-decorators-legacy

Babel-plugin-transform-decorators-legacy is a popular Babel plugin used to transform legacy decorators in JavaScript code. Despite its popularity, there are several common issues that developers may encounter when using this plugin. In this response, we will discuss three of the most common problems with this plugin, their descriptions, and possible solutions.

Problem 1: Decorators not being applied to classes

One common issue that developers encounter is when decorators are not being properly applied to classes. This can happen when the plugin is not correctly configured or when there are conflicts with other Babel plugins.

To address this issue, developers should ensure that the plugin is properly installed and configured in their project. Additionally, they can try disabling other Babel plugins to see if there are conflicts. The following code block shows an example of how to install and configure the plugin:

 

npm install babel-plugin-transform-decorators-legacy --save-dev
// .babelrc
{
  "plugins": [
    "transform-decorators-legacy"
  ]
}

Problem 2: Incorrect scope of decorator function

Another issue that developers may face is when the decorator function is not being applied to the correct scope. This can happen when using decorators on class methods, and the function is not properly scoped to the class instance.

To address this issue, developers can use the “autobind-decorator” package, which automatically binds the decorator function to the class instance. The following code block shows an example of how to use the “autobind-decorator” package:

 

import autobind from "autobind-decorator";

class MyClass {
  @autobind
  myMethod() {
    // ...
  }
}

Problem 3: Syntax errors and unexpected behavior

A third common issue that developers may encounter when using the plugin is syntax errors and unexpected behavior. This can happen when using decorators in conjunction with other language features or libraries that may not be compatible with the plugin.

To address this issue, developers should ensure that the plugin is compatible with the other language features and libraries that they are using. They can also try updating to the latest version of the plugin or using alternative plugins that provide similar functionality. The following code block shows an example of using an alternative plugin, “babel-plugin-transform-decorators”:

 

npm install babel-plugin-transform-decorators --save-dev
// .babelrc
{
  "plugins": [
    ["transform-decorators", { "legacy": true }]
  ]
}

In summary, the babel-plugin-transform-decorators-legacy plugin is a popular tool for transforming legacy decorators in JavaScript code. However, developers may encounter several common issues when using this plugin, including decorators not being applied to classes, incorrect scope of decorator function, syntax errors, and unexpected behavior. To address these issues, developers can ensure that the plugin is properly installed and configured, use the “autobind-decorator” package, or use alternative plugins that provide similar functionality.

 

A brief introduction to babel-plugin-transform-decorators-legacy

Babel-plugin-transform-decorators-legacy is a Babel plugin used to transform legacy decorators in JavaScript code. Decorators are a language feature that allows developers to add metadata to classes and class members, such as methods and properties. This can help simplify code and improve code readability. However, this feature is not natively supported in all JavaScript engines, so developers must use a Babel plugin to transform the code into a compatible format.

Babel-plugin-transform-decorators-legacy specifically targets legacy decorators, which are an older version of the decorator syntax that was proposed but not included in the final version of the ECMAScript specification. This plugin works by modifying the abstract syntax tree (AST) of the JavaScript code to replace legacy decorators with a format that is compatible with the current ECMAScript specification. Additionally, the plugin can also apply decorators to methods and properties, allowing developers to add metadata to their code in a more streamlined manner. Overall, Babel-plugin-transform-decorators-legacy is a useful tool for developers who want to use decorators in their JavaScript code and need to ensure compatibility with a wide range of JavaScript engines.

Most popular use cases for babel-plugin-transform-decorators-legacy

  1. Transforming legacy decorators: Babel-plugin-transform-decorators-legacy can be used to transform legacy decorators in JavaScript code into a format that is compatible with the current ECMAScript specification. This can help developers who want to use decorators in their code but need to ensure compatibility with a wide range of JavaScript engines. For example, the following code block uses the @autobind legacy decorator to bind a method to its class instance:

 

import autobind from "core-decorators/lib/autobind";

class MyClass {
  @autobind
  myMethod() {
    // ...
  }
}
  1. Applying metadata to classes and class members: Babel-plugin-transform-decorators-legacy can also be used to apply metadata to classes and class members, such as methods and properties. This metadata can be used to simplify code and improve code readability. For example, the following code block uses the @readonly decorator to mark a property as read-only:

 

class MyClass {
  @readonly
  myProperty = 42;
}
  1. Ensuring compatibility with older JavaScript engines: Babel-plugin-transform-decorators-legacy can be used to ensure compatibility with older JavaScript engines that do not natively support decorators. By transforming legacy decorators into a compatible format, developers can use this language feature without worrying about compatibility issues. For example, the following code block uses the @deprecated legacy decorator to mark a method as deprecated:

 

class MyClass {
  @deprecated
  myOldMethod() {
    // ...
  }
}
Share

It’s Really not that Complicated.

You can actually understand what’s going on inside your live applications.

Try Lightrun’s Playground

Lets Talk!

Looking for more information about Lightrun and debugging?
We’d love to hear from you!
Drop us a line and we’ll get back to you shortly.

By submitting this form, I agree to Lightrun’s Privacy Policy and Terms of Use.