Unleash Object-Oriented Programming When Consuming APIs
Suppose we are building a Single Page Application and have the following classes (or models in a Angular app):
// user.ts
import { Profile } from './profile';
export class User {
id: number;
first_name: string;
last_name: string;
profile: Profile;
fullName() {
return `${this.first_name} ${this.last_name}`
}
}
// profile.ts
export class Profile {
id: number;
score: number;
goodScore() {
return this.score > 100
}
}
Now, you gotta consume the user api, which returns the following json:
response = `{
"id": 1,
"first_name": "Elon",
"last_name": "Musk",
"profile": {
"id": 10,
"score": 200
}
}`
As soon as you parse your response json, you will get a literal object:
parsed_json = JSON.parse(response)
parsed_json.constructor.name
=> "Object"
The problem is.. A literal object is not a class object, you will not be able to do things like:
user.fullName()
user.profile.goodScore()
We want to use the full power of object-orientation in JavaScript. How can we pull it off?
Enter class-transformer
class-transformer is a small npm package that does the heavy lifting for us.
import { plainToClass } from "class-transformer";
user_instance = plainToClass(User, response)
user_instance.constructor.name
=> "User"
plainToClass
converts a literal object into a class object.
Now we are free to use our methods:
user_instance.fullName()
=> "Elon Musk"
But.. If we try to access a nested object like profile
, it will not work:
user_instance.profile.goodScore()
=> profile.goodScore is not a function
That is because the library does not know which class must be used, so we need to manually define the type (line 9):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// user.ts
import { Profile } from './profile';
import { Type } from "class-transformer";
export class User {
id: number;
first_name: string;
last_name: string;
@Type(() => Profile)
profile: Profile;
fullName() {
return `${this.first_name} ${this.last_name}`
}
}
Ok, now we are good to go:
user_instance.profile.goodScore()
=> true
This library has many more useful functions, I don't want to explain their whole README here, so, go check it out.