Manu Chadha
Manu Chadha

Reputation: 16729

Difference between Javascript object and Typescript object

I am trying to figure out if a Typescript object is same as a Javascript object. I have a typescript variable into which I want to typecast result of JSON.parse which I suppose creates a javascript object from a json but I am unable to do it.

I have the following two classes

export class User {
  constructor (public firstname:string,
               public lastname:string,
               public email:string,
               public password:string=""){} 
}

export class UserProfileAPI {
  'external-profile': User;
  constructor(externalProfile:User){ 
    this['external-profile'] = externalProfile;
  }
}

I have created a spec to test that an object created explicitly is same or similar to object created by json.parse but they don't seem to be.

 fit('should test if Typescript object is same as Javascript object',()=>{
    let user = new User('manu','chadha','[email protected]');
    let dummyUserProfile:UserProfileAPI= new UserProfileAPI(user);
    console.log('dummy profile is ',dummyUserProfile);
    let dummyProfile2:UserProfileAPI = JSON.parse('{"external-profile":{"firstname":"manu","lastname":"chadha","email":"[email protected]"}}');
    console.log('dummy profile 2 is ',dummyProfile2);
    console.log('dummy profile1 == dummy profile 2',(dummyUserProfile == dummyProfile2));
    console.log('dummy profile1 === dummy profile 2',(dummyUserProfile == dummyProfile2));
    expect(dummyUserProfile).toEqual(dummyProfile2);
    expect(dummyUserProfile).toBe(dummyProfile2);
  });

In the above case, dummyUserProfile is printed as LOG: 'dummy profile is ', UserProfileAPI{external-profile: User{firstname: 'manu', lastname: 'chadha', email: '[email protected]', password: ''}} but dummyProfile2 is printed as LOG: 'dummy profile 2 is ', Object{external-profile: Object{firstname: 'manu', lastname: 'chadha', email: '[email protected]'}} and both the comparisons return false. Why?

Upvotes: 1

Views: 1349

Answers (1)

Aaron Beall
Aaron Beall

Reputation: 52133

First of all, as several others have already said in comments: in JS objects never == or === unless they are the same reference. Equality by value doesn't work, ie {} == {} is always false. But given an object like const obj = {} then obj == obj is true. This has nothing to do with TypeScript.

Now to this part of your question:

I am trying to figure out if a Typescript object is same as a Javascript object. I have a typescript variable into which I want to typecast result of JSON.parse which I suppose creates a javascript object from a json but I am unable to do it.

Two important things here you should understand:

  • What you are calling a "TypeScript object" and a "JavaScript object" is really a JavaScript object constructor (or instance of) and a plain JavaScript object. Again this has nothing specifically to do with TypeScript. In ES6 you can define class object types and even in ES5 you can with an old-school constructor function.

  • What you call a "typecast" in TypeScript is really just a type assignment (or you may have tried a type "assertion"), meaning it does not change the object in any way, it just informs the compiler what you assume the type of the object should be. You can assign any to any type, but it doesn't mean it's true. There's actually a lot of ways you can break your code by writing wrong type assignments and assertions.

So your real issue is that JSON.parse() gives you a plain JS object and you want to turn it into a JS object type instance. There's no built-in way to do this in JS unfortunately but of course you can manually do it after decoding the JSON. See: Parse JSON String into a Particular Object Prototype in JavaScript

A simple example in your case might look like this:

function decodeUserFromJSON(userJSON: string): User {
   const userObj = JSON.parse(userJSON);
   const { firstname, lastname, email, password } = userObj;
   const user = new User(firstname, lastname, email, password);
   return user;
}

Depending on how your test framework compares object instances you should be able to check for equality something like this:

const user = new User("a", "b", "[email protected]", "1");
const decodedUser = decodeUserFromJSON(`{"firstname": "a", "lastname": "b", "email": "[email protected]", "password": "1" }`);
expect(decodedUser).toEqual(user);

Upvotes: 2

Related Questions