When to use Class or Interface in Angular project?

AngularTypescriptClassModel

Angular Problem Overview


I’m here today because I’ve a question about, like the title said, about classes and interfaces in Angular.

From my Point of View, I understand this:

Interfaces are used in Typescript to perform type-checking, they are here until the transpilation and disappear in the production. Also Interface cannot be used to instantiate.

Classes came from ES6 are also used for type-checking, but they stay after transpilation and generate code in the production. Also, they are used to instantiate.

So, basically, Interface is useful if we don’t need them in production, if we only need to type-check. On the opposite, Class are here if we need them in production, particularly for the instantiation.

I am Correct or Did I miss something about class and interface?

Angular Solutions


Solution 1 - Angular

You're correct. Interfaces are great when you only need the type checking whereas classes are great when you not only want the type checking, but you need some methods or require some other logic.

Personally, I always start with just using an interface, and once I need some methods, I'll add a class and inherit the interface. I would also add that I prefer to always have an interface whether you're using a class or not. This allows you to pass around/inject the interface instead of having to re-instantiate class multiple times.

Here is an example of a typical pattern I would follow if I need some methods (which means I need a class)

interface IPerson {
    firstName: string;
    lastName: string;
    age: number;
    getFullName(): string;
}
class Person implements IPerson {
    public firstName: string;
    public lastName: string;
    public age: number;
    constructor(firstName: string, lastName: string, age: number) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }
    getFullName(): string {
        return `${this.firstName} ${this.lastName}`
    }
}

const person: IPerson = new Person('John', 'Doe', 44);

I would never inject or need to import Person anywhere unless I actually needed to 'new up' a new person. I can always inject IPerson instead and so long as what was passed in as the class, the interface will allow me call all the class methods and access the properties as I wish.

However, sometimes I don't need methods, but I need a data contract (or just want to suppress TypeScript from being pissed off I'm not telling it what everything is):

interface IPerson {
    firstName: string;
    lastName: string;
    age: number;
}

const person: IPerson = <IPerson>{
    firstName: 'John',
    lastName: 'Doe',
    age: 44
};

Doing it this way still gives you a way to create a variable on the fly that adheres to the interface. However, there are no methods when you do it this way (so you lose your getFullName function and would have to run that manually)

Overall, I find myself using interfaces on http returns that are structured json. I don't really need to do anything more to them on the front end as the backend has done the heavy lifting for me already. So, creating a class for each one of those returns may be overkill, but some people prefer it that way.

One other thing to bring up is that creating all these models is extremely time consuming. It pays off though. In one of my projects, I used an npm module to automatically generate TypeScript interfaces based off my c# models. That saved a ton of typing and thought it was pretty cool (https://www.npmjs.com/package/csharp-models-to-typescript)

One other popular solution is to use Swagger Codegen. You can 'swaggerize' your backend and have swagger codegen just generate your models and services for you. It's pretty slick. Here's an example repo using Angular and C# as the backend.

In general, it's really your preference. Just keep in mind, if you need methods and extra layers to build out a given model, a class is best. If you just need types and don't care about the rest of the fancy 'syntactical sugar' just use an interface. As you mentioned, interfaces disappear in production so it's certainly a plus.

https://jsfiddle.net/mswilson4040/3vznkbq0/7/

Solution 2 - Angular

Since you also tagged Angular in your question, I wanted to add to the answer from an Angular perspective.

Angular also uses the Interface (or class) as a structure when retrieving data via http.

export interface Product {
  id: number;
  productName: string;
  productCode: string;
  tags?: string[];
  price: number;
  description: string;
  imageUrl: string;
}

@Injectable({ providedIn: 'root' })
export class ProductService {
  private productsUrl = 'api/products';

  constructor(private http: HttpClient) { }

  getProducts(): Observable<Product[]> {
    return this.http.get<Product[]>(this.productsUrl);
  }
}

The http.get method gets the data and populates the provided product array structure. This makes it much easier to work with the data from the component.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionScieur ArnaudView Question on Stackoverflow
Solution 1 - AngularmwilsonView Answer on Stackoverflow
Solution 2 - AngularDeborahKView Answer on Stackoverflow