Converting API response into a class instance using `class-transformer` in TypeScript: A step-by-step guide

When working with TypeScript, I have a regular method called

Request(method: HttpMethod, url: string, ...)
that is used for calling APIs.

Now, my goal is to convert the response from this API request into an instance of a class using class-transformer (or maybe without it).

For example:

class UserResponse {
  id: number;
  foo: string;
  bar: string;
}
const user = await Request(HttpMethod.GET, '/user/1');
// The 'user' object should be an instance of the 'UserResponse' class

I am aware that using generics in this manner is not valid:

const Request = <T>(method: HttpMethod, url: string, ...) => {
  // logic to fetch data...
  return plainToClass(T, res);
}

const user = await Request<UserResponse>(HttpMethod.GET, '/user/1');

Although generics do not function in that way, there is a workaround like this:

const Request = <T>(method: HttpMethod, url: string, ..., transformTo?: { new (): T }) => {
  // axios or other fetching mechanism...
  return plainToClass(transformTo, res);
}

const user = await Request(HttpMethod.GET, '/user/1', ..., new UserResponse());

However, even this approach is still giving me a type of 'unknown' for the 'user' object:

const user: unknown

What mistake am I making here?

Answer №1

Firstly, let's discuss the concept of Request. It seems like it probably returns a Promise.

There are a couple of issues in your code:

  1. You are not mapping your response to a new instance of UserResponse.
  2. In TypeScript, generics do not create instances like classes; they act more as data contracts similar to interfaces.

Here is how you should handle this scenario:

class UserResponse {
  public id: number;
  public foo: string;
  public bar: string;
  constructor(user: UserResponse) {
    Object.assign(this, user); // or set each property individually
  }
}
const response = await Request(HttpMEthod.GET, '/user/1');
const user = new UserResponse(response);

To rectify this, you need to define a constructor within your class (or use an interface). Once the constructor is implemented, you can instantiate a new UserResponse object from the response.

If the structure of your Request function resembles the following:

const Request = <T>(method: HttpMethod, url: string, ...,  transformTo?: { new (): T }) => {
  // axios or some other logic...
  return plainToClass(transformTo, res);
}

I suggest modifying your approach like this:

const user = await Request(HttpMEthod.GET, '/user/1', ... , UserResponse);

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

Establishing a restricted channel exclusive to a specific role for joining

I want to create a special channel where only members from the partyInvitees collection (Collection<Snowflake, GuildMember>) can join. const permission = Discord.Permissions.FLAGS; message.guild.createRole({ name: message.author.username + "&apos ...

Top method for triggering an action on the client-side during Sign In with the help of Redux, React, and NextAuth

Currently, I am developing a web application that utilizes the Spotify API. My goal is to seamlessly load the user's playlists as soon as they log in using NextAuth. At the moment, there is a button implemented to trigger playlist loading, but it onl ...

Version 2 of the Microsoft Logo Animation

I made some changes to my Microsoft logo animation project. You can view the updated version on CodePen. Overall, I'm pretty happy with how it turned out except for one issue. I'm struggling to determine the right timing to end the animation so ...

Importing multiple features in Angular

[UPDATE]: Oops, my mind is a bit muddled from fatigue and I've mixed up two ideas which resulted in a rather meaningless question... Let's just blame it on the coffee! :P This may not be a pressing issue but more of a quest for knowledge... ...

Mastering the art of incorporating if..then test flow in Cypress can elevate your testing

I need to create a test in Cypress that loads a page and checks if a modal opens within 5 seconds. If the modal opens, it should close it. If the modal does not open, the test should proceed to the specified testcase in the before block. How can I achiev ...

Nodejs and javascript are utilized to create dynamic SES emails

I have successfully implemented sending an email using node-ses client.sendEmail({ to: to_id, , cc: cc_id, , bcc: bcc_id, , subject: 'greetings' , message: 'your <b>message</b> goes here' , altText: 'plain text& ...

Using JSTL tags may result in returning null or empty values when making Javascript calls or populating HTML

This strange error is puzzling because it appears on some of the webpages I create, but not on others, even though the elements are exactly the same. For instance, this issue does not occur: <main:uiInputBox onDarkBG="${hasDarkBG}" name="quest ...

Using a PHP variable to trigger the jQuery .show() function

I'm attempting to trigger jQuery .show() events based on PHP variables. Below is my PHP code (retrieved from a form submission on another page): $last_pic_displayed = trim($_POST["last_pic_displayed"]); if (strlen($last_pic_displayed) <= ...

JavaScript (specifically, using jQuery) in conjunction with AJAX

After using validation with jQuery in JavaScript and applying it to ASP.NET controls within an AJAX update panel, I encountered a problem. The validations are working correctly, but the event of the button control is still being executed despite the valida ...

What could be causing the Autocomplete feature to display as undefined?

I'm encountering an issue where the Autocomplete box displays "undefined" even though it returns the expected results. How can I resolve this problem? import { Drawer, List, Typography, Switch, ListItem, ListItemText, ListItemSecondaryAction, TextFiel ...

What could be causing one of my images to not appear on my Gatsby page?

Hey there, I could use some help with this issue: Recently, I created a website using Gatsby.js and deployed it to my web server (which is running NGINX on Ubuntu 20.04). The site uses Gatsby Image for querying and displaying images, and everything seems t ...

Leveraging Angular Firebase MatTable with the power of 2 observables in 1

I'm currently facing an issue with my Firebase database data structure where I have a reference to a user id. Here's an example of the original data in my collection: { city: new york, country: usa addedBy: feibf78UYV3e43 // This is the USER ID ...

Using Javascript to map an array with objects from a different array and then returning the computed array

I'm struggling to solve a seemingly simple issue. I have an array that looks like this: Array 1: [ { "id": 1, "date": "2019-03-27", "time": 1, "max_tasks": 3, "reservations": [ 5, 2 ...

What is the best way to retrieve the identifier for a specific role?

Struggling to acquire a channel permissions overwrite by obtaining the ID of a role stored in a variable. Any suggestions on how I can access the ID of this new role? This problem has been consuming my time for several days now. I have experimented with t ...

Creating a 2D image of a Three.js scene in JPG format: Is it possible?

I am working with a three.js scene that includes rendering a 3D cube. The code snippet for the scene setup is shown below: var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHe ...

Arranging date and time in jQuery based on AM/PM notation

I have written some JavaScript code to sort dates in ascending order (from newest to oldest). I have successfully sorted the dates, but I am having trouble sorting the time with AM or PM using a 12-hour format. I can do it in a 24-hour format, but not in ...

Inter-component communication in Angular

I am working with two components: CategoryComponent and CategoryProductComponent, as well as a service called CartegoryService. The CategoryComponent displays a table of categories fetched from the CategoryService. Each row in the table has a button that r ...

Mongoose: Unable to fetch item using its specific identification - Error 404

I've been attempting to fetch objects from MongoDB using Mongoose, but I keep encountering a 404 error. router.get('/blogs/:id', function(req, res){ console.log('trying to get one blog post by id'); Blog.findOne({ _id: req.para ...

How can I hide a root layout component in specific nested routes within the app directory of Next.js?

Is there a way to prevent rootlayout from being wrapped around dashboardlayout? Explore the latest documentation for Next.js version v13: https://i.sstatic.net/M0G1W.png Take a look at my file structure: https://i.sstatic.net/nVsUX.png I considered usi ...

I am encountering issues with my PostCSS plugin not functioning properly within a Vue-cli 3 project

I developed a custom postcss plugin that was working perfectly according to the postcss guidelines until I tried to implement it in a real project. For reference, here's the plugin on GitHub My goal is to integrate it into a Vue-cli app using Webpac ...