How to make type-safe HTTP requests in Angular?

Statically typed languages like TypeScript are particularly beneficial for large-scale projects. As the codebase grows, the ability to define and enforce types becomes increasingly essential. TypeScript’s type system helps prevent common errors and enables developers to refactor and restructure code confidently. As Angular is based on TypeScript, it provides a number of features that can help in writing type-safe HTTP requests using HttpClient.

When we make an HTTP request using the Angular HttpClient service, we can specify the type of response that we expect. This will help the TypeScript compiler to ensure that we are using the response data correctly. Here is a step-by-step guide for this process:

Create an interface

Suppose we need to use Gutendex API to derive the title and download_count of a particular book having 1 ID. In order to avoid any type-related errors, we’ll define a Book interface to define the structure of the book data. Here is the sample interface:

export interface Book {
title:string,
download_count:number,
}

Create a service for HTTP eequest

In this step, we’ll create a service using the ng generate service app command. This service will be used to send the HTTP GET request to the Gutendex API. Let’s have a look at the following app.service.ts file:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Book } from './book';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AppService {
constructor(private http:HttpClient) { }
apiURL = "https://gutendex.com/books/1"
getBookDetails(): Observable<Book> {
return this.http.get<Book>(this.apiURL)
}
}

In the above file:

  • Line 14: Import the required packages and interfaces.

  • Line 11: Create the private instance of HttpClient in the constructor.

  • Line 12: Define the API’s endpoint URL.

  • Line 1416: Define the getBookDetails() function that returns the Observable of the Book interface response type. This function sends an HTTP GET request to the API URL by mentioning the type. Just before the get function is called, the <Book> syntax is defined. This is an example of a type parameter.

Use the service to get data

Next, we’ll use the service in the app.component.ts file to get data from the API. Following is the app.component.ts file using the service:

import { Component, OnInit } from '@angular/core';
import { AppService } from './app.service';
import { Book } from './book';
import { Observable, map } from 'rxjs';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{
books$ !: Observable<Book>
constructor(private appService:AppService){}
ngOnInit() {
this.books$ = this.appService.getBookDetailsType().pipe(map((data:any)=>{
return {
title: data.title,
download_count: data.download_count
}
}))
}
}

In the above code:

  • Line 14: Import the required dependencies and files.

  • Line 12: Declare an Observable named books$ of type Book.

  • Line 14: Inject the service into the component.

  • Line 1823: The code maps the observable this.appService.getBookDetailsType() to a new observable this.books$, extracting and renaming specific properties (title and download_count) from the emitted data. Since the expected response type is defined, the component now contains the type checking and code completion.

Display the results

In the app.component.html file, we’ll display the required properties, title and download_count, extracted from the service. Following is the complete overview of the methods we defined in the above steps:

import { Component, OnInit } from '@angular/core';
import { AppService } from './app.service';
import { Book } from './book';
import { Observable, map } from 'rxjs';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{
  books$ !: Observable<Book>

  constructor(private appService:AppService){}

  ngOnInit() {

   this.books$ = this.appService.getBookDetails().pipe(map((data:any)=>{
    return {
      title: data.title,
      download_count: data.download_count
    }
   }))

  }
}
The complete example of Type-safe HTTP request

By running the above project, we can see the title and download_count on the user interface.

Conclusion

By following these steps, we can make type-safe HTTP requests in Angular, ensuring that we’re working with well-defined data structures and catching errors at compile-time.


Free Resources

HowDev By Educative. Copyright ©2025 Educative, Inc. All rights reserved