loading...

How I removed a ton of if statements from my Angular app

ionellupu profile image Ionel lupu Updated on ・2 min read

Maybe you don't make the same mistakes like I do in Angular, but I wanted to share with you how I removed a lot of if statements from my code by simply using parameters in methods.

Let's imagine you have an UserComponent that shows the user's name and there is a button to delete it:

import { Component, OnInit } from '@angular/core';

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

@Component({
    selector: 'app-user',
    template: `
        <p>Welcome {{user.name}}!</p>
        <button (click)="removeUser()">Remove user</button>
    `
})
export class UserComponent implements OnInit {

    user?: User;

    async ngOnInit() {
        this.user = await fetchUser(1);
    }

    async removeUser() {
        if (this.user) { // this is what we will remove later
            await removeUser(this.user.id);
        }
    }
}

This works fine (assuming we've implemented the fethUser and removeUser functions) even if we build for prod with ng build --prod.

But when working with Typescript, you will hear everyone saying to enable strict mode to protect developers against common errors. You can do it inside the tsconfig.json file:

{
    "compilerOptions": {
        "strict": true
    }
}

The app still works, but if we are trying to build for production now, we will get the following error:

ERROR in src/app/user/user.component.ts.UserComponent.html(2,12): Object is possibly 'undefined'.

This is because Angular is trying to protect us against undefined values by checking our templates. In this case, the user variable has the type User|undefined. This is fine. We can fix this by using a condition in the template:

    <ng-container *ngIf="user">
        <p>Welcome {{user.name}}!</p>
        <button (click)="removeUser()">Remove user</button>
    </ng-container>

This will fix all the errors, but we have two if conditions in our app and we are trying to get rid of most of them.

Type checking in templates work the same as in typescript: types are narrowed if a condition is used. This means that the user variable inside the ng-container will only have the type User because the undefined type was stripped by the *ngIf directive.

This means we can now pass the user as a parameter to the removeUser method and remove the if from there. This is the final component:

import { Component, OnInit } from '@angular/core';

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

@Component({
    selector: 'app-user',
    template: `
        <ng-container *ngIf="user">
            <p>Welcome {{user.name}}!</p>
            <button (click)="removeUser(user)">Remove user</button>
        </ng-container>
    `
})
export class UserComponent implements OnInit {

    user?: User;

    async ngOnInit() {
        this.user = await fetchUser(1);
    }

    async removeUser(user: User) {
        await removeUser(user.id);
    }
}

Do you have any other sweet tips like this one? Share them in comments! 😁

Follow me on Twitter for more awesome stuff like this.
Check Typetron, the Node.js framework I am working on.

Posted on by:

ionellupu profile

Ionel lupu

@ionellupu

Author of Typetron. Passionate about web development. Typescript enthusiast.

Discussion

pic
Editor guide
 

This is the pattern than I generally use as well. I find it works quite well. I'll also often include a "loading" UI when the user is not yet available.