Creating a TypeScript class to extend the JavaScript object prototype

tl;dr: My goal is to apply compiled Typescript prototype definitions to objects I have defined as classes.


Situation: I am looking to enhance a JavaScript object with business logic specified in a typescript class.
For example:

class Address
{
  constructor(
    public Street: string,
    public Number: number,
    public Zip: number,
    public City: string)
  { }

  public get FullAddress()
  {
    return this.Street + ' ' + this.Number + ', '
      + this.Zip + ' ' + this.City;
  }
}

The compiled JS code adds the extension to the object prototype using FullAddress. When calling

new Address('Somestreet', 5, 3564, 'SomeCity')
everything works smoothly.


The Problem: When receiving a JS object (e.g., via angular's $http)

$http.get('/api/address').then((answer: AngularPromise<Address[]>) => 
{
  console.log(answer.data[0].FullAddress());
});

The issue arises when trying to call FullAddress on the object because Typescript merely defines it in the class without modifying the actual object.


Attempted Solution: One workaround could be to instantiate each object individually as shown below:

$http.get('/api/address').then((answer: AngularPromise<Address[]>) => 
{
  for(var i = 0; i < answer.data.length; i++)
  {
    answer.data[0] = new Address(answer.data[0].Street, ans.....);
  }
  console.log(answer.data[0].FullAddress());
});

This approach may involve overloading the Address constructor to accept the complete object to minimize redundancy.


The actual Question: Given that the object structure I require is more intricate than the simplistic Address example provided here, the above solution would lead to excessive boilerplate. I am seeking a more efficient way to address this dilemma.

Answer №1

Dealing with a similar issue myself! One approach, as mentioned before, is creating a constructor and manually inputting all the data - a bit cumbersome and doesn't feel quite right. Instead, we developed a MapTo function that can efficiently map a generic object to a specific class:

public static MapTo(jsonObject, namespace, classType) {
    var instance = new classType();
    for (var prop in jsonObject) {
        if (!jsonObject.hasOwnProperty(prop)) {
            continue;
        }

        if (jsonObject[prop] == null) {
            instance[prop] = null;
        } else if (typeof jsonObject[prop] === 'object') {
            if (namespace[prop]) {
                instance[prop] = this.MapTo(jsonObject[prop], namespace, namespace[prop]);
            } else {
                instance[prop] = jsonObject[prop];
            }
        } else {
            instance[prop] = jsonObject[prop];
        }
    }

    return instance;
}

To use this function:

var convertedObject = MapTo(answer.data[0], Models, Models.Address); //Assuming your class resides in a namespace named "Models"

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

What is the best way to display a Bootstrap pop-up and then automatically hide it after a few seconds

Does anyone know how to display a Bootstrap popup when the page loads and automatically hide it after 3 seconds? I found an example online but I'm unsure how to adapt the code for my specific needs. <button type="button" class="btn btn-primary" da ...

Using the spread syntax to copy properties of a React component may result in an error

I've been experimenting with the spread syntax in React and I've encountered an issue. When trying to destructure props using the spread operator, I keep getting an error message: const { className, children, ...otherprops } = this.props; Has a ...

Understanding the concept of hoisting in JavaScript for global variables and functions

I've been curious about hoisting. I understand that if a global function shares the same name as a global variable, the function will overwrite the variable's name. Is this correct? Here is an example code snippet. (function() { console.log ...

Exploring how Angular mat-checkbox can be targeted within dynamically generated nested elements

I am facing a challenge with a series of checkboxes that I create using mat-checkbox, including a corresponding Select all checkbox. What I want to achieve is to selectively hide the specific (and first) checkbox without affecting any other elements within ...

Having difficulty launching a TypeScript Node.js application using ts-node and pm2

I have a node app built with TypeScript and it works fine with nodemon, but when I try to move it to the server using PM2, I encounter errors. I've searched GitHub and StackOverflow for solutions, but nothing has worked for me so far. Any help would b ...

What is the purpose of passing the Promise constructor as a second argument in knex migration examples?

When using Knex, migration files are used to make changes to the database structure, and they can be applied or rolled back. To create a new migration file, you can use the following command in the cli: knex migrate:make migration_name After running this ...

Is there a potential memory leak issue with Express.js running on Node.js?

For a basic project, I've been utilizing express with Node.js on a Heroku server. However, after implementing New Relic to monitor memory usage, I noticed a gradual memory leak. To troubleshoot, I removed all custom code and extra Node modules, leavin ...

Error in Displaying Vuetify Child Router View

I am currently working on integrating a child router-view to be displayed alongside surrounding components. Here is an overview of my routing setup: { path: "/login", name: "TheLoginView", component: TheLoginView, }, { path: "/dashboa ...

Tips for unit testing an Angular Service that is primarily responsible for redirecting to an external page from the application

My service is responsible for redirecting to a separate login page since we are implementing login as a service. function redirectToMembership() { var returnURL = $location.host(); returnURL+="/#/Authorization"; $window.location.href=Environme ...

Designate material for a particular table header element

Is there a method to pass content within a td-element to a specific th-element? I am working with a dynamic table and need to associate the content correctly under each table header. I have implemented pagination for the rows in the table. Currently, all ...

Promise.all doesn't pause for Firestore queries to iterate

The code I am converting from the Realtime Database to Firestore involves looping through each User (doc) in Firestore and then through each document of 2 nested Subcollections inside each User in order to create some jobs to be handled later. Although I ...

Access information from a different component within the route hierarchy

Suppose you have three components named A, B, and C with the following routing direction: A -> B -> C To retrieve data from the previous component (going from C to get data from B), you can use the following lines of code: In Component C: private ...

Transmitting Filter Choices as an Object for Retrieving Multiple Values within an Angular Application

In my Angular application, I have a function that takes user selections for various filter types and sends a request to the API to retrieve filtered data based on those selections. Each filter type returns values in an array format, allowing users to selec ...

jquery sequential fade effect

I am trying to make each div fade in one by one. Visit this link for reference <div id="w"> <div class="one"></div> <div class="two"></div> <div class="three"></div> </div> $(function() { $(&a ...

Tips on executing an asynchronous operation before exiting

I have been attempting to execute an asynchronous operation before my process ends. By 'ends', I mean in every instance of termination: ctrl+c Uncaught exception Crashes End of code Anything.. As far as I know, the exit event handles this for ...

Error encountered while trying to run a three.js example with iewebgl

I'm attempting to utilize the iewebgl and encountering difficulties while trying to run an example from three.js, specifically the webgl_loader_obj. Upon execution, I am facing the following error: SCRIPT445: Object doesn't support this action i ...

What is causing the error message "Error: Cannot update active font: 'Fira Sans' is not included in the font list" in react-font-picker?

For my project, I have implemented a font picker component in the following manner: <FontPicker apiKey={process.env.REACT_APP_GOOGLE_API_KEY} activeFontFamily={activeFontFamilyMobile} ...

jquery code to count the number of children in an html table

I'm struggling to grasp the behavior of the jquery method children. I can successfully count the number of <p> elements within a <div> using the following code: var abc = $("div").children("p"); alert(abc.length); However, when I a ...

retrieve the chosen option from the dropdown menu

Whenever I try to display the input type based on the selection from a select element, I encounter an issue Here is the select element within my view: <select id="type" name="type_id" class="form-control" required> @foreach($type as $row) & ...

jQuery appears to be unresponsive or inactive

I'm trying to implement a jQuery script that will slide in a header after scrolling on the page, but for some reason, it's not working. When I reach the 3rd line, my code editor displays a !read only alert, suggesting there may be a syntax issue? ...