Bird
Raised Fist0
Angularframework~5 mins

Generics in Angular services

Choose your learning style10 modes available
Introduction

Generics let you write flexible Angular services that work with different data types without repeating code.

When you want one service to handle multiple data types, like users and products.
When you want to keep your code clean and avoid copying similar service logic.
When you want type safety while reusing the same service methods.
When you build reusable data-fetching or data-processing services.
When you want to create a service that adapts to different models easily.
Syntax
Angular
export class DataService<T> {
  private data: T[] = [];

  add(item: T): void {
    this.data.push(item);
  }

  getAll(): T[] {
    return this.data;
  }
}

The <T> after the class name means this service uses a generic type called T.

You can replace T with any type when you use the service, like DataService<User>.

Examples
This service fetches an array of any type T from an API.
Angular
import { Observable } from 'rxjs';

export class ApiService<T> {
  fetchAll(): Observable<T[]> {
    // fetch data logic
    return new Observable<T[]>();
  }
}
This service stores and retrieves items of any type T.
Angular
export class StorageService<T> {
  private items: T[] = [];

  save(item: T): void {
    this.items.push(item);
  }

  getItems(): T[] {
    return this.items;
  }
}
Sample Program

This Angular service uses generics to store and retrieve different types of data. We create one service instance for users and another for products. Each stores its own type safely.

Angular
import { Injectable } from '@angular/core';

interface User {
  id: number;
  name: string;
}

interface Product {
  id: number;
  title: string;
}

@Injectable({ providedIn: 'root' })
export class GenericService<T> {
  private items: T[] = [];

  add(item: T): void {
    this.items.push(item);
  }

  getAll(): T[] {
    return this.items;
  }
}

// Usage example
const userService = new GenericService<User>();
userService.add({ id: 1, name: 'Alice' });
userService.add({ id: 2, name: 'Bob' });

const productService = new GenericService<Product>();
productService.add({ id: 101, title: 'Book' });

console.log(userService.getAll());
console.log(productService.getAll());
OutputSuccess
Important Notes

Remember to specify the type when creating the service instance, like new GenericService<User>().

Generics help catch type errors early, making your code safer and easier to maintain.

Summary

Generics let Angular services work with any data type without rewriting code.

Use <T> to define a generic type placeholder in your service.

Specify the actual type when you create the service to get type safety and flexibility.

Practice

(1/5)
1. What is the main benefit of using <T> in Angular services?
easy
A. It allows the service to work with any data type without rewriting code.
B. It makes the service run faster by optimizing memory.
C. It automatically generates UI components for the service.
D. It restricts the service to only one specific data type.

Solution

  1. Step 1: Understand the role of generics in Angular services

    Generics use <T> as a placeholder to allow services to handle different data types flexibly.
  2. Step 2: Identify the benefit of this flexibility

    This flexibility means you don't have to rewrite the service for each data type, saving time and effort.
  3. Final Answer:

    It allows the service to work with any data type without rewriting code. -> Option A
  4. Quick Check:

    Generics = Flexible data types [OK]
Hint: Generics mean one service fits many data types [OK]
Common Mistakes:
  • Thinking generics improve speed
  • Believing generics auto-create UI
  • Assuming generics limit data types
2. Which of the following is the correct syntax to declare a generic Angular service class?
easy
A. export class DataService<T> { }
B. export class DataService { }
C. export class DataService<T>() { }
D. export class DataService<T> => { }

Solution

  1. Step 1: Recall the syntax for generic class declaration in TypeScript

    The correct syntax uses angle brackets after the class name with a type parameter, like class ClassName<T>.
  2. Step 2: Match the syntax to Angular service class

    export class DataService<T> { } correctly shows export class DataService<T> { }, which is valid for a generic service.
  3. Final Answer:

    export class DataService<T> { } -> Option A
  4. Quick Check:

    Generic class syntax = class Name<T> [OK]
Hint: Generic classes use <T> right after the class name [OK]
Common Mistakes:
  • Adding parentheses after <T>
  • Using 'extends' without a type
  • Using arrow functions for class declaration
3. Given this generic service snippet:
export class DataService<T> {
  private items: T[] = [];
  add(item: T) { this.items.push(item); }
  getAll(): T[] { return this.items; }
}

const service = new DataService<string>();
service.add('hello');
service.add('world');
console.log(service.getAll());

What will be logged to the console?
medium
A. Error: Type mismatch
B. [hello, world]
C. ['hello', 'world', undefined]
D. ['hello', 'world']

Solution

  1. Step 1: Understand the generic type used

    The service is created with string as the type, so items is an array of strings.
  2. Step 2: Trace the add and getAll methods

    Two strings 'hello' and 'world' are added, then getAll() returns the array with these two strings.
  3. Final Answer:

    ['hello', 'world'] -> Option D
  4. Quick Check:

    Generic array with strings = ['hello', 'world'] [OK]
Hint: Generic type <string> means array holds strings [OK]
Common Mistakes:
  • Thinking output is unquoted strings
  • Expecting extra undefined elements
  • Assuming type errors at runtime
4. Identify the error in this generic Angular service code:
export class DataService<T> {
  private items: T[] = [];
  add(item: T) { this.items.push(item); }
  getAll(): T[] { return this.items; }
}

const service = new DataService();
service.add(123);
medium
A. Method getAll() should return a Promise.
B. Cannot push item to array inside the service.
C. Missing generic type argument when creating service instance.
D. Service class cannot have private properties.

Solution

  1. Step 1: Check service instantiation

    The service is created without specifying the generic type <T>, so TypeScript cannot infer the type.
  2. Step 2: Understand consequences of missing generic type

    Without the type, the compiler may treat T as any or cause errors, losing type safety.
  3. Final Answer:

    Missing generic type argument when creating service instance. -> Option C
  4. Quick Check:

    Always specify <T> when creating generic service [OK]
Hint: Always add <T> when new-ing generic services [OK]
Common Mistakes:
  • Ignoring missing generic type argument
  • Thinking private properties cause errors
  • Expecting getAll() to return Promise
5. You want to create a generic Angular service that fetches data from an API and returns typed results. Which approach correctly combines generics with Angular's HttpClient to ensure type safety?
hard
A. Use get(url: string): Observable<any> and cast results manually after subscribing.
B. Use get<T>(url: string): Observable<T> in the service method and specify type when calling.
C. Use get(url: string): Promise<T> without generics and rely on JSON parsing.
D. Use get<T>(url: string): Observable<string> to always return strings.

Solution

  1. Step 1: Understand Angular HttpClient generic method

    HttpClient's get<T> method allows specifying the expected data type for the response.
  2. Step 2: Ensure type safety by specifying T when calling

    By using get<T>(url), the returned Observable emits data typed as T, ensuring compile-time checks.
  3. Final Answer:

    Use get<T>(url: string): Observable<T> in the service method and specify type when calling. -> Option B
  4. Quick Check:

    HttpClient generics = type-safe API calls [OK]
Hint: Use HttpClient get<T>() for typed API responses [OK]
Common Mistakes:
  • Using any instead of generics loses type safety
  • Casting manually after subscription is error-prone
  • Returning Observable<string> ignores actual data shape
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard