Reputation: 1274
I'm new to angular came from angularjs, and I'm confused about rxjs observable.
Example:
User.ts
export class User {
id?:any;
username:string;
password:string;
}
With <User[]>
myUser(header: any) {
const url = `${this.mainUrl}/my_user`;
return this.http.get<User[]>(url, header).pipe(
map(resp => {
return resp;
})
);
}
Without <User[]>
myUser(header: any) {
const url = `${this.mainUrl}/my_user`;
return this.http.get(url, header).pipe(
map(resp => {
return resp;
})
);
}
This will return the same result. So I'm confused on whats the difference, with or without it.
EDIT:
This is the data I'm fetching nowhere near look like my User.ts
but its not throwing an error.
{
"username": "mhqadmin",
"inserted_at": "2019-02-06T07:01:17.024874",
"id": "b491e7c3-da11-40fe-b4b7-8f97fa88a9fd",
"avatar": {
"middlename": "mhqadmin",
"lastname": "headquarters",
"id": "939c2eec-573e-4245-adcc-0771c73f22e4",
"firstname": "marte"
},
"app_role": "mhq-admin",
"app_permission": true
}
Upvotes: 0
Views: 152
Reputation: 919
The difference between this.http.get<User[]>
and this.http.get
is that you're passing a type into the generic signature of get
.
From the Angular source code:
get<T>(url: string, options?: {
headers?: HttpHeaders | {[header: string]: string | string[]},
observe?: 'body',
params?: HttpParams|{[param: string]: string | string[]},
reportProgress?: boolean,
responseType?: 'json',
withCredentials?: boolean,
}): Observable<T>;
The get<T>
stands for a generic type signature, it means that you can declare what the data should look like. When you declare this.http.get<User[]>
, you're saying that the data that comes back should look like an array of User
- but that is all a TypeScript based idea, it's unrelated to RxJS/Observables/JavaScript. When you call this.http.get
, you're still just using a JavaScript runtime, it's just making an HTTP request for data. Passing an interface into a generic signature does not force the actual data coming back to change - but it enhances your type safety by enabling the TS compiler to understand what the data should look like.
EDIT:
It appears that you want to pick pieces of data off to match your User.ts
class. By providing a type, like this: this.http.get<User[]>
, that will not change the data, it will only hint to the code editor what the data should look like, but it doesn't touch the data at all. You'll need to actually pluck the data out if you want to change the shape of it to match your User.ts
class, something like this:
myUser(header: any) {
const url = `${this.mainUrl}/my_user`;
return this.http.get(url, header).pipe(
map(resp => {
return {
id: resp.id,
username: resp.username
};
})
);
}
That would help you match to an interface/class that looks like this:
interface User {
id: string;
username: string;
}
But that is not the shape of the data, or the type of your data that you are getting, that looks more like this:
interface User {
username: string;
inserted_at: string;
id: string;
avatar: Avatar;
app_role: Role;
app_permission: boolean;
}
That is a type that better matches what is actually coming back from your backend. With whatever type you pass into the generic, that will be the model for what is coming out of the Observable, but you'll need to then match the actual interface correctly, as I've done in the map
example.
Upvotes: 2
Reputation: 8295
With <User[]>
you instruct Typescript that the return of http.get
is an Observable<User[]>
so it will infer the type of myUser
to Observable<User[]>
. This is very helpful further in your application since the tooling will know what properties exist on your reponse types and if you did a mistake/typo. It will also fail during compile time if you access properties that don't exist. That is because http.get
is a generic method where you can specify the response type (but if you don't specify it, it uses any).
Without <User[]>
, typescript will just use the any
type, which brings no additional benefit over plain javascript.
Also map(resp => { return resp; })
is useless and you can safely remove it.
Upvotes: 2