Issue with TypeChecking in Angular4's HttpClient

I have been reading about how the new Angular's HttpClient can perform TypeChecking. Based on that information, I have written the following code:

post(path: string, body: Object = {}): Observable<ValorTest> {
return this.http.post<ValorTest>(path, JSON.stringify(body))
  .map((data: ValorTest) => {
    console.log(typeof data); // Why does the console display 'data' as object instead of ValorTest?
    console.log(data instanceof ValorTest); // outputs: false
    console.log(data); // outputs (no type displayed in Chrome's console): {codigo: "INF00001", estado: "Success"}
  })
  .pipe(catchError(this.formatErrors));

}

I am receiving a JSON object that matches my model class (ValorTest).

Question: Why is the console.log displaying the type of data as object instead of ValorTest?

Answer №1

If you're simply performing type checking or assertions, you can utilize the instanceof operator. However, if you wish to display the class name, you can access it using data.constructor.name:

class TestClass {}

var instance  = new TestClass();

console.log(typeof instance);
// Expected result: "object"

console.log(instance.constructor.name);
// Expected result: "TestClass"

if (instance instanceof TestClass) {
    console.log("instance is TestClass");
}
// Expected result: "instance is TestClass"

Explanation behind this approach: typeof operator only works with JavaScript's native data types like string, boolean, object, etc. By examining how TypeScript transpiles into JavaScript, you can understand why JavaScript identifies your instance as an "object" at runtime.

Updated

This method is applicable only for instances created using the new class() constructor. HttpClient does not actually instantiate your class -- it mainly allows you to define the expected response data type for development purposes with TypeScript. HttpClient does not enforce these expectations at runtime. If you need strict type checking during runtime, you may need to create your own type guard function.

For instance, if you have a class similar to:

class TestClass {
    prop: string;
    constructor() { }
    method(): void {}
}

You can construct a type guard like this:

function isTestClass(obj: TestClass | object): obj is TestClass {
    // Add necessary type checking logic here
    return (<TestClass>obj).method !== undefined && 
           (<TestClass>obj).prop !== undefined; 
}

To validate your data at runtime:

var obj_a = { prop: "" },
    obj_b = { prop: "", method: null };

console.log(isTestClass(obj_a));
// Expected result: false

console.log(isTestClass(obj_b));
// Expected result: true

You can consider making the type guard function a static method of your class.

Additionally, using an interface for response data instead of a class may be beneficial, as it conveys that the received data may not match the expected implementation.

Further details on user-defined type guards at: https://www.typescriptlang.org/docs/handbook/advanced-types.html

Answer №2

When using the typeof call, it will only output JavaScript's built-in types. If you are looking to check for a specific custom type, you should use the instanceof operator, as it will indicate whether the returned value matches your custom type!

Answer №3

When it comes to TypeScript, the code gets converted to JavaScript for browser compatibility. The browser then uses objects to handle the converted code, which results in the console only recognizing objects.

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

The function argument does not have the property 'id'

I created a function that authorizes a user, which can return either a User object or a ResponseError Here is my function: async loginUser ({ commit }, data) { try { const user = await loginUser(data) commit('setUser', user) ...

Deploying Angular 7 with a separate .Net Core API on Azure: A Comprehensive Guide

Currently, my setup involves a .Net Core Application with Angular 7 serving as the Client. Both the API and Client have been successfully deployed on Azure. However, I am facing an issue in getting the client to properly communicate with the .Net Core end ...

Angular 6: Issue TS2339 - The attribute 'value' is not recognized on the 'HTMLElement' type

I have a textarea on my website that allows users to submit comments. I want to automatically capture the date and time when the comment is submitted, and then save it in a JSON format along with the added comment: After a comment is submitted, I would li ...

What is the best way to ensure that a class instance only receives the necessary properties?

In my code, I have a function that takes in an object called DataObject and uses certain properties from it to create instances of a class. To determine which data object items should be assigned to which class properties, I use mappings in the form of a ...

Issue: "Exported functions in a 'use server' file must be async"

I'm currently working on implementing layout.tsx in the app directory of Next.js 13 to create a navigation layout that appears on all pages. I've successfully configured it so that the navbar updates when a user logs out or signs in, but there&ap ...

When running npm install, an ERESOLVE error message may appear indicating that a resolution could

Upon executing npm install, I encounter the following error message: code ERESOLVE npm ERR! ERESOLVE could not resolve npm ERR! npm ERR! While resolving: @angular-devkit/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d8baadb1b ...

What is the best way to insert more rows into a mat-table without disrupting the existing layout?

Having trouble adding 2 additional columns (status and buttons) after the ngfor. It seems to be disrupting the entire structure, as shown in the image below: View the Broken Table Screen Shot I am making modifications based on code from material.angular. ...

Replicating the Angular project folder is not effective

Instructions for using Angular's quickstart script are as follows: git clone https://github.com/angular/quickstart.git quickstart cd quickstart npm install npm start If I follow these steps, everything works perfectly. However, if I duplicate this d ...

Incorporate the Angular router within markdown hyperlinks

When utilizing ngx-markdown to display my FAQ, I include links to both external resources (beginning with http) and internal content (starting with /). I am interested in passing the Angular router to my markedOptionsFactory so that I can easily navigate ...

Can you verify that the client's date and time locale are accurate in JavaScript before proceeding with processing?

For my application, I am seeking the current locale datetime. However, before retrieving the date, it is crucial to verify that the local date and time are accurate. If the user has adjusted the date and time incorrectly on their machine, I must prompt a ...

Working with undefined covariance in TypeScript

Despite enabling strict, strictNullChecks, and strictFunctionTypes in TypeScript, the following code remains error-free. It seems that TypeScript is not catching the issue, even though it appears to be incorrectly typed. abstract class A { // You can p ...

Angular 6 combined with Firebase is experiencing difficulties with routing after a successful login

After spending hours trying to fix my issue, I still can't figure it out. I've searched through related threads on SO, but haven't found a solution yet. Issue After successfully signing up, the email verification flag is set to true. Howev ...

Utilizing Typescript for Efficient Autocomplete in React with Google's API

Struggling to align the types between a Google address autocomplete and a React-Bootstrap form, specifically for the ref. class ProfileForm extends React.Component<PropsFromRedux, ProfileFormState> { private myRef = React.createRef<FormContro ...

Adding a new document to an existing collection with an array field in MongoDB

Having an issue with adding a new chapter to my var array. Here is the code snippet in question: array.push({ chapter: [ { id: 2, title: 'adsf', content: &ap ...

Angular correctly displaying specific array items within button elements

I am facing an issue with my dashboard where I have 4 items in an array and 4 buttons on display. My goal is to assign each item with a specific button, but currently, it shows 4 buttons for each "hero" resulting in a total of 16 buttons. I have tried usin ...

Struggling to set a theme for Angular Ag Grid within an Angular 10 project

Currently, I am working on a project where Angular 10 is being used along with ag-grid-community version 25.1. When running the application with ag-theme-alphine.css, I encountered the following error: Error: Failed to locate '../node_modules/ag-grid- ...

Tips for dynamically modifying style mode in Vue.js

I am looking to implement a feature where the style can be changed upon clicking a button. In my scenario, I am using Sass/SCSS for styling. For example, I have three different styles: default.scss, dark.scss, and system.scss. The code for dark.scss look ...

Is there a way for me to set a variable in my component with a value from the Angular Material autocomplete feature?

I am currently in the process of constructing a form to generate a POST request to the API. I have opted to utilize Angular Material 4 and incorporate the Autocomplete component provided by Material Design. Below is the code snippet displaying my HTML Com ...

Merge information from two sources utilizing concatMap

I am encountering an issue where I need to extract a specific value from the data obtained from my first service in order to pass it on to the second service. Angular seems to have trouble with 'firstserviceResultsJson.indSsn'. How can I successf ...

Link a list separated by commas to checkboxes in Angular 9

Within my reactive form, I am binding a checkbox list to an array using the following structure: {id:number, name:string}. TS ngOnInit(): void { this.initFCForm(); this.addCheckboxes(); } initFCForm(): void { this.fcForm = this.formBuilder.group({ fr ...