1

I've read that the new Angular's HttpClient can perform TypeChecking, based on that I write 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 console displays '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'm receiving a JSON that matchs with my model class (ValorTest).

Question: why the console.log displays the type of data as object instead of ValorTest ?

2
  • It's just type checking you should care about casting to ValorTest class yourself Commented Mar 4, 2018 at 13:38
  • 1
    Because either what you've read is plain wrong, or you didn't really understand it. All HttpClient is doing is JSON.parse() to transform the bytes in the body to an object. JSON.parse doesn't know and care about your class. It creates POJOs, and these POJOs will never be instances of any class. Commented Mar 4, 2018 at 13:40

3 Answers 3

2

If you're just doing typechecking / assertion, you can use instanceof. If you actually need to print the name of the class, you can try data.constructor.name:

class TestClass {}

var instance  = new TestClass();

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

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

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

As for the why: typeof only works with JavaScript's built in data types, such as string, boolean, object, etc. If you look at the way TypeScript transpiles to JavaScript, you can make sense of why at runtime JavaScript only knows that your instance is an "object".

Updated

This will only work on instances that are created with the new class() constructor. The HttpClient is not actually creating an instance of your class for you here -- it's basically just allowing you (for development purposes) to specify with TypeScript the kind of data you expect to receive in the response. As far as I know, the HttpClient does nothing to ensure (at runtime) that the response data actually meets those expectations. If you require strong type checking at runtime, you would probably need to write your own type guard function.

So if you had a class like this:

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

You could write a type guard like this:

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

And check your data at runtime:

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

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

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

I might make the type guard function a static method of my class.

Also, as an aside, you might consider using an interface for your response data instead of a class -- mostly because it might help drive the intuition that the data you've received may or may not have the implementation you expect.

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

Sign up to request clarification or add additional context in comments.

2 Comments

Hi, using instanceof returns fase. The JSON I'm reading matchs the model structure
@RafaelReyes I've updated my answer after reading your response. Does this help explain things a bit?
1

The typeof call will only emit JS's built in types, what you probably want to do is checking for instanceof, which will tell you if the returned value is matching your custom type!

2 Comments

Quick appendix: it's important to keep in mind that TypeScript is structural, not nominal, meaning that even an object matching the structure of your custom type will emit true in this case. If you want to check the actual typing of your variable, simply log it without typeof or instanceof, Chrome's console will tell you the type!
Hi, I've already edited the question based on your comments. Using 'instanceof' returns false and when logging the single object (data) the Chrome's console doesn't display the type, it displays the structure of thedata.
0

not related to HttpClient,all the typescript codes and types convert to javascript that browser can compile, then javascript handle them using objects, so in console it just knows objects.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.