Reader Stacks

TypeScript Interfaces in Angular, With Examples

An interface defines a shape data must conform to, purely at compile time — it disappears entirely from the compiled JavaScript, unlike a class.

A TypeScript interface defines the shape data must conform to — which properties exist, and their types — purely as a compile-time construct that catches type mismatches during development and disappears entirely from the final compiled JavaScript.

Defining a basic interface

interface Product {
    id: number;
    name: string;
    price: number;
    inStock: boolean;
}

Using it to type a variable or function parameter

const product: Product = {
    id: 1,
    name: 'Widget',
    price: 19.99,
    inStock: true,
};

function displayProduct(product: Product): string {
    return `${product.name} — $${product.price}`;
}

Assigning an object missing a required property, or with a mismatched type, produces a compile-time TypeScript error — this is the actual value an interface provides, catching mistakes before the code ever runs rather than surfacing as a runtime bug.

Optional properties

interface Product {
    id: number;
    name: string;
    price: number;
    description?: string; // optional — the ? marks it as not required
}

Typing an HTTP service's response with an interface

@Injectable({ providedIn: 'root' })
export class ProductService {
    constructor(private http: HttpClient) {}

    getProducts(): Observable {
        return this.http.get('/api/products');
    }
}

Typing the HTTP response with the interface (Observable) gives autocomplete and compile-time type checking on every property accessed from the API response throughout the component consuming this service.

Extending an interface

interface Product {
    id: number;
    name: string;
    price: number;
}

interface DetailedProduct extends Product {
    description: string;
    specifications: Record;
}

Extending an interface builds a more specific shape on top of a shared base — useful when a detail view needs additional fields beyond what a summary list view requires from the same underlying entity.

Interface vs. class: the key practical difference

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

class ProductClass {
    constructor(public id: number, public name: string) {}
}

An interface exists only at compile time and produces zero runtime JavaScript — a class, by contrast, compiles to a real, instantiable JavaScript constructor function. Use an interface purely for typing plain data shapes (like an API response); use a class when the type also needs actual behavior (methods) or needs to be instantiated with new.

Using type aliases as an alternative to interfaces

type Product = {
    id: number;
    name: string;
    price: number;
};

A type alias can express nearly the same thing as an interface for a plain object shape — interfaces are generally preferred by convention for object shapes specifically because they support declaration merging and are slightly more idiomatic in most Angular style guides, though the practical difference for a simple data shape like this is minor.