Reputation: 163
I declared a typed variable that will supposedly hold the data fetched by a service. However, the returned data is not the same type as the variable, yet the variable still accepts the data.
Here is my code:
Data: Array<{Currency: string, Rate: number}>;
getData(): void {
this.DataService.getAll().subscribe(
(res: Array<any>) => {
this.Data = res;
},
(err) => {
console.log(err);
}
);
}
I tried the following but it still didn't work:
res: Array<{Currency: string, Rate: number}>
Update
This is my service
getAll(): Observable<Array<{Currency: string, Rate: number}>> {
return this.http.get(`${this.baseUrl}/data`).pipe(
map((res) => {
this.data = res['data'];
return this.data;
}),
catchError(this.handleError));
}
UPDATE 2
I found the similar issue here: https://github.com/angular/angular/issues/20770
Upvotes: 0
Views: 164
Reputation: 5462
You can create a model as:
export interface CurrencyModel {
Currency: string,
Rate: number
}
then use this model in response as:
Data: CurrencyModel[];
getData(): void {
this.DataService.getAll().subscribe(
(res: CurrencyModel[]) => {
this.Data = res;
},
(err) => {
console.log(err);
}
);
}
getAll
should return Observable<CurrencyModel[]>
Upvotes: 1
Reputation: 1602
Because there is no type safety at runtime.
Remember TypeScript is translated into JavaScript at compile time. And at that point, all bets are off.
If you want to ensure some sort of type safety I recommend using something for API documentation with tooling for automated code generation like OpenAPI with swagger.
Upvotes: 0
Reputation: 2270
TypeScript is an extension on top of JavaScript that provides type support for the process of writing code. Anyways, all your TypeScript code will be converted to pure JavaScript before you can run your program. Thus, after compilation all your types will be lost in reality.
If your returned data at runtime do not have the same type as the variable you declared, there is no chance for TypeScript to warn you or prevent this. This is because TypeScript can only check static types, not dynamic types like if you receive a server response. You'll need another validation mechanism to verify your server data correspond to your TypeScript definition.
Upvotes: 0
Reputation: 249476
any
is by definition assignable to anything. So Array<any>
will be assignable to any other array type. I would avoid any
at all cost. If you truly don't know the type of somethign use unknown
instead and use explicit assertions as needed, better explicit assertions rather than silent any
assignments.
Data: Array<{Currency: string, Rate: number}>;
getData(): void {
this.DataService.getAll().subscribe(
(res: Array<unknwon>) => {
this.Data = res as Array<{Currency: string, Rate: number}>;
},
(err) => {
console.log(err);
}
);
}
Ideally getAll()
should return Observable<Array<{Currency: string, Rate: number}>>
. The no type annotations would be necessary on res
and it would all be type safe.
Upvotes: 0