Hello everyone,
in today's article, I wanted to briefly illustrate one of the features of Angular that has left me pleasantly satisfied: the Inject function.
Note: All the code used in this article can be found here.
TABLE OF CONTENTS:
Introduction to Inheritance in TypeScript
Before delving into the explanation of the Inject function, I wanted to briefly touch on inheritance in TypeScript. Inheritance is a process in OOP that allows us to extend our classes by inheriting methods and fields from other classes. In TypeScript, you can achieve this using the extends keyword, like this:
interface IAnimal {
dateOfBirth: any;
}
interface IDog extends IAnimal {
breed: any;
}
class Animal {
resident: IAnimal ;
constructor(animal: IAnimal) {
this.resident = animal;
}
}
class Dog extends Animal {
constructor(dog: IDog, private parameter2: number) {
super(dog);
}
}
As you can see in the constructor of the Dog class, if we want to inject or add additional dependencies in the constructor of the child class, we must necessarily use the super function and inject the inherited dependencies from the base class into it. Of course, this means that if the Animal class had 10 dependencies, we would need to inject all 10 dependencies in the super call.
The Inject function
Once we have a good understanding of inheritance in TypeScript, we can introduce the first benefit of using the new Inject feature in Angular, which precisely relates to not having to use the super
function to inherit dependencies from a parent class. Let's take the example of a basic service:
// base-service.service.ts
export abstract class BaseService {
http: HttpClient = inject(HttpClient);
}
// user.service.ts
@Injectable({
providedIn: 'root',
})
export class UserService extends BaseService {
getAll() {
return this.http.get<User[]>('/users');
}
}
as you can see, instead of inserting dependencies inside the constructor, we have simply created a variable of type protected, which will then be inherited by child classes.
Another benefit also relates to the use of inject outside of a component or service class. It could be used, for example, to create a function that dynamically retrieves a router param like this:
import { inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
export function getRouteParameter(param: string) {
const router = inject(ActivatedRoute);
return router.snapshot.paramMap.get(param);
}
to then be used in
import { CommonModule } from '@angular/common';
import { Component, inject, OnInit } from '@angular/core';
import { RouterLink } from '@angular/router';
import { getRouteParameter } from '../../utility';
import { User } from '../user.model';
import { UserService } from '../user.service';
import { Observable } from 'rxjs';
import { UserAddressPipe } from '../../user-address.pipe';
@Component({
selector: 'app-user-detail',
standalone: true,
imports: [CommonModule, RouterLink, UserAddressPipe],
providers: [UserService],
templateUrl: './user-detail.component.html',
})
export class UserDetailComponent implements OnInit {
userId: string | null = '';
user$!: Observable<User>;
private userService: UserService = inject(UserService);
constructor() {
this.userId = getRouteParameter('id');
}
ngOnInit(): void {
if (this.userId != null)
this.user$ = this.userService.getById(+this.userId);
}
}
making the HTTP call from the service in this way.
And with that, we can conclude our brief overview of the inject
function and its uses. If you found this article helpful, please consider sharing it and leaving a review ❤️.
Happy Coding!!
Top comments (1)
Just be careful, can only be used in an inject context, for example in a constructor