I'm getting to know Angular, TypeScript and RxJS. I have an http request that returns a JSON. In this JSON there is data that I need to construct my defined object. Let's say, that my object is this:
export class RegularUser {
constructor(
public id: number,
public firstName: string,
public lastName: string,
public token: string
) {}
}
Now, I am sending a request to some API, which returns data in this format:
{
success: boolean,
uid: number,
first_name: string,
last_name: string,
cid: number,
rights: number[]
token: string
}
I have the HttpClient service, so I thought I would do:
this.httpClient.get(
'http://api.example.com/api/get_user'
).pipe(
tap((receivedData: Response) => console.log(receivedData)),
map((receivedData: Response) => {
return new RegularUser(
receivedData.uid,
receivedData.first_name,
receivedData.last_name,
receivedData.token);
})
);
But for TypeScript, the receivedData
object doesn't have above-listed params. Do I have to create an interface for the API response and then map it to my RegularUser
object?
The http requests in TypeScript can be placed using a function called fetch() function. The fetch() function takes two parameters, namely URL and options and returns a Response object.
To convert JSON to the interface, the developer does not need to do anything. simply write code that follows some rules to allow the typescript compiler to do the conversion. First, the Interface is defined with properties the same as JSON fields.
catch( (error: Response) => { return Observable. throw(error); } );
You can specify a type for get()
such as an interface. Why an intermediary/additional interface may be warranted for separation of concerns in your situtation is that get()
with a type will not new up an instance of class RegularUser
. An intermediary/additional interface can be created with properties you expect from the server response that will be used to create an instance of your end class:
interface Foo {
uid: number,
first_name: string,
last_name: string,
token: string
}
this.httpClient.get<Foo>(
'http://api.example.com/api/get_user'
).pipe(
tap((receivedData: Foo) => console.log(receivedData)),
map((receivedData: Foo) => {
return new RegularUser(
receivedData.uid,
receivedData.first_name,
receivedData.last_name,
receivedData.token);
})
);
If you do not need to new up an actual instance of class RegularUser
, it may be enough it to just have it as an interface or class with properties:
this.httpClient.get<RegularUser>(
'http://api.example.com/api/get_user'
).pipe(
tap((receivedData: RegularUser) => console.log(receivedData))
);
Hopefully that helps!
Instead of constructor, use interface which is a better alternative. So IDE can enable code autocompletion using the Language Service and wrong naming of properties can be avoided.
export interface RegularUser {
success: boolean;
uid: number;
first_name: string;
last_name: string;
cid: number;
rights: number[];
token: string;
}
In service:
this.httpClient.get<RegularUser>(
'http://api.example.com/api/get_user'
).pipe(
tap((receivedData: RegularUser) => console.log(receivedData))
);
You can create your own Response
interface by using:
export interface MyResponse {
success: boolean,
uid: number,
first_name: string,
last_name: string,
cid: number,
rights: number[]
token: string
}
And then import it into your service:
import { MyResponse } from '../some/path/filename.ts';
But you can also include it in your service itself, so you can skip 'export'
.
You can just use it just like your current Response
interface:
(receivedData: MyResponse)
Note: you can give it any name you want (use TitleCase for consistency). You can also use names already used by Angular, which will then be overwritten, but that's not recommended. See comments.
You may have to make some properties optional (?:
), otherwise you may get a red line indicating that 'some properties are missing' if not all are used:
...
success?: boolean,
...
Or, you can just remove the warning by making it type any
, but that's not recommended:
(receivedData: any)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With