ionic/angular- How to use interfaces correctly?

13,027

Solution 1

Interfaces in Typescript only provide a description of the shape of an object. If an object is created in TypeScript, the compiler can reason about whether the object is compatible with the interface. At runtime interfaces are erased, so there will be no check as to whether an object is compatible with an interfaces. When you make a request using post<T> you are basically telling the compiler that the shape of the object you expect as a response if T but no checking will be performed to ensure this.

You can have as many interfaces as you like in a file, and you can export them from that file an import them in another file just like you would a class or function. How you organize your code is up to you.

If you want ensure an object is correctly implemented at runtime see here

Solution 2

As you mentioned interfaces in typescript is for just defining a contract. So in your example it is just that you are expecting a log in response from the server with the properties you have mentioned in the interface. There is no constraint like in the interface we should mention all the properties returning in the JSON response. You can even add more properties in the interface if you want which is not present in the JSON response. So in your specific example by making use of interfaces you can get to know what is the specification of an API when you check the code in future. So below will be my implementation

I will create a new file called ILoginRequest.ts and declare interface called ILoginRequest

export interface ILoginRequest {
 email:string;
 password:string;
}

And use that interface as the type of the requestData input parameter in provider class

login(reqData:ILoginRequest ): Observable<LoginResponse[]> {
return this.http.post<LoginResponse[]>('localhost:3000/api/login', reqData);

}

So if we use the login function in the provider class anywhere else in the project we know what should be the input that need to given to the login method and what is the expected result from that function.

And in the calling page will assign the output from the api in loginResponse variable which is interface LoginResponse type. so where ever we use this variable in the class we know what all are the properties we can use and we get intelliSense support in IDE

export class LoginPage {
 private loginResponse : LoginResponse;
 constructor(private loginService: LoginServicesProvider) {
 }

onSubmit() {
let reqParams = {
email: '[email protected]',
password: 'password',
};

this.loginService.login(reqParams).subscribe((res:LoginResponse) => {
    console.log('success');
    this.loginResponse = res;
});

} }

For more detailed information about the interface usage in typescript you can check this link.

About where to keep the interface, according to me it is just developers preference, you can create separate folder called interfaces in 'app' directory and create new file for each interfaces.

Share:
13,027
version 2
Author by

version 2

A software professional with 3.8 years of diverse experience in Software Development.

Updated on June 22, 2022

Comments

  • version 2
    version 2 almost 2 years

    I'm pretty new to angular/ionic app development. I read the following somewhere

    Interfaces are only at compile time. This allows only you to check that the expected data received follows a particular structure.

    I'm making an ionic app and the API services returns some data back to user. Let's say it's a login function and the API service returns data for that.

    I made a provider in Ionic from where HTTP calls are made to API using HTTPClient.

    //Provider
    
    import { HttpClient } from '@angular/common/http';
    import { Injectable } from '@angular/core';
    import { Observable } from 'rxjs/Observable';
    
    interface LoginResponse {
      success: boolean;
      message: string;
      token: string;
      userId: number;
    }
    @Injectable()
    export class LoginServicesProvider {
      constructor(public http: HttpClient) {
      }
    
      login(reqData): Observable<LoginResponse[]> {
        return this.http.post<LoginResponse[]>('localhost:3000/api/login', reqData);
      }
    }
    

    As you can see, I created an interface called LoginResponse

    And the code for the Login component is as follows:

    //Component
    
    import { LoginServicesProvider } from './../../providers/login-services/login-services';
    import { Component } from '@angular/core';
    import { Observable } from 'rxjs/Observable';
    
    @Component({
      selector: 'page-login-page',
      templateUrl: 'login-page.html',
    })
    export class LoginPage {
      constructor(private loginService: LoginServicesProvider) {
      }
    
      onSubmit() {
        let reqParams = {
        email: '[email protected]',
        password: 'password',
        };
    
        this.loginService.login(reqParams).subscribe(res => {
            console.log('success');
        });
      }
    }
    

    For this example, I just print a message to console.

    Now comes my questions

    1) Like mentioned in the earlier statement, is my LoginResponse interface checking the data received? If not, how/where I should implement that check- in provider or component?

    2) If I have multiple interfaces inside a single provider, let say, one for login data and other for user profile data or something, where should I place it? Can I keep it in a separate file and export it? I didn't see any ionic commands to create interfaces

    Thanks! I don't wanna start my career from mistakes. That's why I thought of posting this.

  • mehany
    mehany about 6 years
    I ld also add, It is also a great way to communicate with other developers on your project ( or even yourself 10 months later ) the shape of objects