What is the best way to set a value to a decorated property within the constructor of a parent class

I am facing an issue with initializing a decorated property "name" in a User class within the parent class constructor (Base) using Object.assign. The value ends up being "undefined" when the decorator is present, but it works correctly when the decorator is removed. This problem persists even though I am using TypeScript version 5.4.2.

Can someone provide assistance or guidance on how to resolve this issue and make it work as intended?

Thank you.

// test.ts
(Symbol as any).metadata ??= Symbol("Symbol.metadata") // Polyfill

function Value(value: string) {
    return (_target: any, context: ClassFieldDecoratorContext) => {
        context.metadata![context.name] = value
    }
}

class Base {
    constructor(data: any) {
        Object.assign(this, data)
    }
}

interface IUser {
    id?: string
    name?: string
}

class User extends Base implements IUser {
    id?: string

    constructor(data: IUser) {
        super(data)
    }

    @Value("test")
    name?: string
}

const data = {
    id: "1",
    name: "John Doe"
}

const user = new User(data)
// user.id is 1
// user.name is undefined

Answer №1

This issue has been identified as a bug in TypeScript and has been reported on microsoft/TypeScript#56000.

The discrepancy stems from how modern JavaScript handles public class fields compared to the original implementation in TypeScript. When declaring a class field in a JavaScript subclass, it is initialized as `undefined` and is not automatically inherited from the superclass. To align TypeScript behavior with JavaScript, you must enable the `--useDefineForClassField` flag. This adjustment is crucial for future compatibility.

In addition, there have been changes in TypeScript's approach to decorators starting from version 5.0 to better reflect their functionality in JavaScript.

It appears that downleveling for JavaScript decorators in TypeScript always assumes the `--useDefineForClassField` flag is active. Consequently, even if the flag is disabled, decorated fields will behave as if it is enabled, leading to the observed `undefined` behavior.

While this issue is likely to be addressed in a future update, it is advisable to anticipate using JS class fields alongside JS decorators. As JavaScript runtimes adopt decorators, they are also expected to support class fields. Attempting to combine new decorators with older field implementations may result in compatibility issues down the line.

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

Issue encountered with express-jwt and express-graphql: TypeScript error TS2339 - The 'user' property is not found on the 'Request' type

Implementing express-jwt and graphql together in typescript has been a challenge for me. import * as express from 'express' import * as expressGraphql from 'express-graphql' import * as expressJwt from 'express-jwt' import s ...

Steps to fix: "Rule '@typescript-eslint/consistent-type-assertions' is missing a definition"

My React app is failing to compile because it can't find the rule definition for '@typescript-eslint/consistent-type-assertions'. I'm feeling quite lost at the moment. I can't seem to locate any current rule definitions within the ...

Developing Your Own Local Variable in Angular with Custom Structural Directive ngForIn

I am hoping for a clear understanding of this situation. To address the issue, I developed a custom ngForIn directive to extract the keys from an object. It functions correctly with the code provided below: import {Directive, Input, OnChanges, SimpleChan ...

Angular 6 and above: The use of ProvidedIn in a submodule is leading to a circular dependency issue

A resolve service is being implemented using the new providedIn attribute. This translations resolver is utilized in a protected module: import { Injectable } from '@angular/core'; import { Observable , pipe } from 'rxjs'; import { ...

The request/response is missing property "x" in type "y" but it is required in type "z" during fetch operation

I have configured an interface specifically for utilization with an asynchronous function: interface PostScriptTagResponse { script_tag : { readonly id : number , src : string , event : string , readonly created_at : string , readonl ...

"Encountering issues with Angular2's FormBuilder and accessing nested object properties,

As I dip my toes into TypeScript and Angular2, I find myself grappling with a nested object structure in an API. My goal is to align my model closely with the API resource. Here's how I've defined the "Inquiry" model in TypeScript: // inquiry.ts ...

Identifying the specific type within a union of types using a discriminator

How can I specify the correct typing for the action argument in the function withoutSwitchReducer as shown below? enum ActionTypesEnum { FOO = 'FOO', BAR = 'BAR', } type ActionTypes = { type: ActionTypesEnum.FOO, paylo ...

What is the best way to eliminate duplicate data from an HTTP response before presenting it on the client side?

Seeking assistance on how to filter out duplicate data. Currently receiving the following response: {username:'patrick',userid:'3636363',position:'employee'} {username:'patrick',userid:'3636363',position:&a ...

Can anyone provide guidance on incorporating jQuery typing into an angular2 seed project?

I'm struggling to incorporate jQuery typings into my Angular2-seed project. Within my component, I am utilizing jQuery in the following manner: declare let $: any; export class LeafletComponent implements OnInit { ngOnInit(): void { th ...

How can you dynamically disable a radio option button using Angular rendering without relying on an ID?

Is there a way to disable the male radio button without using an id, and utilizing angular rendering2? It seems like it's not working for me. I need to make this change only in the form.ts file, without altering the HTML code. form.html <label& ...

What methods are typically used for testing functions that return HTTP observables?

My TypeScript project needs to be deployed as a JS NPM package, and it includes http requests using rxjs ajax functions. I now want to write tests for these methods. One of the methods in question looks like this (simplified!): getAllUsers(): Observable& ...

Using TypeScript with React: Initializing State in the Constructor

Within my TypeScript React App, I have a long form that needs to dynamically hide/show or enable/disable elements based on the value of the status. export interface IState { Status: string; DisableBasicForm: boolean; DisableFeedbackCtrl: boolean; ...

Resolving the name error: Importing definition files from node_modules/@types in Angular

After acquiring this set of definitions from a node_modules/@types file, I encountered an issue trying to import it into my js file. I went ahead and executed npm install @types/p5 before including it in my tsconfig.json as follows: "types": [ "n ...

A guide on cycling through keys in an object with changing values using Typescript

Struggling with a beginner question here - I'm having trouble iterating through an object with dynamic keys in Typescript //This is how I've typed my object let obj: { [key: string]: string } = {}; Using forEach or map isn't working and thr ...

Getting the item that was clicked on a Chart in a PrimeNG chart within an Angular application can be achieved by following these

I am trying to implement a bubble chart and I would like the function to be called when a user clicks on one of the bubbles. What is the best way for me to pass the data to this function? https://i.stack.imgur.com/FYiSP.png <p-chart type="bubble" [da ...

Ways to retrieve the quantity of a particular value within an object using TypeScript

I'm inquiring about how to retrieve the number of a specific value within an object using TypeScript. Here is the structure of the object: obj : TestObject = { name: "test", street: "test" subobj1: { status: warning, time: ...

Guide on utilizing a declaration within a third-party module

I have encountered an issue while using the fingerprintjs2 library, as the declaration provided in DefinitelyTyped seems incomplete and incompatible. In order to resolve this, I decided to create my own declaration within my project. However, I am facing ...

To determine if two constant objects share identical structures in TypeScript, you can compare their properties

There are two theme objects available: const lightMode = { background: "white", text: { primary: "dark", secondary: "darkgrey" }, } as const const darkMode = { background: "black", text: { prim ...

Leverage Ramda's clone function within a pipeline in a manner that ensures type safety

My goal is to utilize Ramda for cloning and updating objects in a type-safe manner, drawing inspiration from this approach. However, I am facing challenges implementing it in a type-safe way. Updating a nested object seems to work perfectly fine in a type ...

Update the android constructor to utilize onCreate() method

Is it true that constructors should not be used, and instead onCreate() should be utilized? If so, how can I make this replacement? I am interested in using onCreate() because I want to incorporate vibration with the system services. Within MainActivity: ...