The difference between a class and data in the shape of a class in TypeScript

I came across an issue that stems from the way objects behave in JavaScript/TypeScript that is different than the C# behavior. So I thought I would jot it down for the next time I have this problem...

Defining the class and Http method

Let's say we have an object with title and tags properties. In our UI, we want to display those values concatenated together. Rather than store this displayName property, I would create a synthetic property and return a calculated value:

export class Thing {
  public title: string;
  public tags: string;
  
  public get displayName(): string {
    return `${title} [${tags}]`;
  }
}

My Thing object is returned from an Http request.Typescript does allow for declaring the type of the data payload. (In this example, TResponse represents the type of data returned from the call.)

const sendHttpRequest = async <TResponse>(url: string): Promise<TResponse> {

  // snip...
    
  aadClient
    .fetch(url, AadHttpClient.configurations.v1, options)
    .then((response: HttpClientResponse): Promise<TResponse> => {
      return response.json();
    })
    .then((data: TResponse) => {
      resolve(data);
    })
    .catch((error: Error) => {
    reject(error);
  });
};

Invoking the sendHttpRequest method requires a Type, and is also pretty straight-forward:

let data = await sendHttpRequest<Thing>("https://someapi");

Reviewing the response

In C#/.Net, deserializing the response returns an instance of the specified type. I can see three properties on the variable. However, it does not work this way in TypeScript.

The call to response.json() returns an object. But this is a JavaScript/JSON object. Which is not necessarily my Thing object. It may look like a Thing, but it certainly does not act like a Thing!

Even though I specified a type for the Http response (in the .Net vocabulary, I "closed the generic type"), JavaScript will not necessarily create an object using the complete definition (called the prototype). So, while TypeScript will happily transpile my code, and JavaScript will execute without errors, trying to access the displayName property of the returned object results in "undefined."

A typical pattern in .Net would be to use the JsonConverter class to convert JSON to a specific type. But in the above code, there is no explicit conversion to a type. It is simply converting a string to an object.

Resolving the issue

Before I try to access the displayName property, I need to create an instance of my Thing object. In my scenario, I can simply create and assign values:

let thing = Object.assign(new Thing(), data);

NOTE: There is a lot to understand about Object.assign and inheritance and nested objects. Be sure to do your research!