Interface vs Type Alias

Comparison

Featureinterfacetype
Object shapesyesyes
Unions, tuples, primitivesnoyes: type Id = string | number
Extendingextendsintersection &
Declaration mergingyes (same name merges)no (duplicate name is an error)
Mapped / conditional typesnoyes
Error messagesshows the interface namesometimes shows the expanded type

The Same Shape Both Ways

Example

interface CartItemI {
  productId: number;
  qty: number;
}

type CartItemT = {
  productId: number;
  qty: number;
};

const a: CartItemI = { productId: 1, qty: 2 };
const b: CartItemT = a; // same shape, fully compatible
console.log(b);

type PaymentMode = "UPI" | "CARD" | "COD"; // only a type alias can do this
const mode: PaymentMode = "UPI";
console.log(mode);

Output

{ productId: 1, qty: 2 }
UPI

Tip: A simple team rule: use interface for object shapes (especially public APIs and classes) and type for unions, tuples, function types and computed types. Most important is to be consistent.