1

Having the following sample models:

interface User {
  id: string
  organization: Organization
}

interface Organization {
  id: string
}

When I send a request, for example:

const user = new User("abc", new Organization("xyz"))
httpClient.post<User>(url, user)

Understandably, it looks like this:

{
  "id": "abc",
  "organization": {
    "id": "xyz"
  }
}

How can I send a request that looks like the following, instead?

{
  "id": "abc",
  "organization": "xyz"
}

I was hoping there would be some kind of mechanism to transform a request in HttpClient, but I can’t find anything.

Another approach was to convert the User to a plain JS object and manipulate it, but I can’t figure out how to do it:

const user = new User("abc", new Organization("xyz"))
const data = Object.assign({}, user);

data.organization = data.organization.id; // error, can’t assign string to Organization

So data is still a User, not a plain JS object.

What’s the best way to achieve it?

Pawel Decowski
  • 1,602
  • 2
  • 15
  • 23
  • Does this answer your question? [How can I convert a TypeScript object to a plain object?](https://stackoverflow.com/questions/37300338/how-can-i-convert-a-typescript-object-to-a-plain-object) – Apoorva Chikara Aug 25 '21 at 10:57

2 Answers2

0

So data is still a User, not a plain JS object.

You are creating an instance of User to send the data and the object data is type of User always.

If you want to send plain object, de-structure the objects and create one object literal:

const org = new Organization("xyz"), 
      user = new User("abc", {organization: org.organization.id}),             
      {id, organization} = user,
      payload = {id, organization};

// why do you need to create org or user if you can directly assign and create an object like this

// const payload = {id: "abc" , organization: "xyz" };
httpClient.post<User>(url, payload)
Apoorva Chikara
  • 8,277
  • 3
  • 20
  • 35
  • Your first solution won’t work because `organization` has to be of type `Organization`, which has an `id` property and you’re passing a plain object with `organization` property. I know the data type is `User`. What I said was that the data type is still `User` after creating a new (seemingly plain) object with `Object.assign({}, user)`. As to why I’m using models if I can “directly assign and create an object”: models provide data safety and, optionally, methods to manipulate the data. Plain objects can do neither. – Pawel Decowski Aug 25 '21 at 10:46
  • `Object.assign({}, user)` clones/copy the object so it is also copying the type from instance, check [this](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign). `Your first solution won’t work ` yes it is possible if you have a type check in user class. – Apoorva Chikara Aug 25 '21 at 10:54
  • You should check [this](https://stackoverflow.com/questions/37300338/how-can-i-convert-a-typescript-object-to-a-plain-object). – Apoorva Chikara Aug 25 '21 at 10:57
0

I found one solution but I’m not 100% happy with it. I won’t accept it for now, in case someone can offer a better one.

Edit: marked as accepted answer.

const user = new User("abc", new Organization("xyz"));

// clone the `user` object as I don’t want to modify the original
// (this step is optional)
const data = Object.assign({}, user);

// overwrite the `organization` property on the object
// with the value of `organization.id`
Object.assign(data, { organization: data.organization.id });

httpClient.post<User>(url, data)

To keep it clean, I added it as a method on the User class:

class User
{
    constructor(
        id: string,
        organization: Organization
    ) { }

    asRequestData()
    {
        const data = Object.assign({}, this);
        Object.assign(data, { organization: data.organization?.name });

        return data;
    }
}

httpClient.post<User>(url, user.asRequestData())
Pawel Decowski
  • 1,602
  • 2
  • 15
  • 23