Skip to main content
Go back

TypeScript #3: Objects and Interfaces

#typescript #objects #interfaces

How to shape your data. Interfaces, Types and why "any" is your enemy.

So far we’ve seen primitive types (string, number, boolean). But the real world runs on objects. Users, Products, Orders… they are all objects with multiple properties.

The Anarchy of Anonymous Objects

In pure JavaScript, we often pass objects around trusting our memory.

javascript
function printUser(user) {
  // 🤞 Let's hope 'user' has these properties...
  console.log("Name: " + user.name.toUpperCase());
  console.log("Age: " + user.age);
}

// A month later, someone calls the function like this:
printUser({ nombre: "Alice", edad: 30 }); 
// 💥 CRASH: Cannot read properties of undefined (reading 'toUpperCase')
// Why? Because we passed "nombre" (Spanish) but the function expected "name" (English).

TypeScript prevents this by forcing you to define the SHAPE of your objects.

Interfaces: The Contract

An interface is like a contract. If an object claims to be a User, it MUST fulfill the contract.

typescript
interface User {
  name: string;
  age: number;
  isDeveloper: boolean;
}

const alice: User = {
  name: "Alice",
  age: 39,
  isDeveloper: true
}; // ✅ Fulfills the contract

const pepe: User = {
  name: "Pepe"
}; // ❌ Error: Missing properties 'age' and 'isDeveloper'

Optional Properties (?)

Sometimes we don’t have all the data. Maybe the email is optional. For that, we use the question mark ? after the property name.

typescript
interface Product {
  id: number;
  name: string;
  description?: string; // 👈 Optional (string | undefined)
}

const desk: Product = {
  id: 1,
  name: "Desk"
  // No need to include description
};

Read-only Properties (readonly)

If you want to ensure that a property never changes after creating the object (like an ID), use readonly.

typescript
interface Configuration {
  readonly apiKey: string;
  theme: "light" | "dark";
}

const config: Configuration = {
  apiKey: "xyz-123",
  theme: "light"
};

config.theme = "dark"; // ✅ You can change this
config.apiKey = "abc-999"; // ❌ Error: Cannot assign to 'apiKey' because it is a read-only property.

type vs interface?

You’ll see people using type User = { ... } instead of interface User { ... }. To define the shape of an object, both work almost the same.

Golden Rule (for now):

  • Use interface to define objects that represent entities (User, Post, Product).
  • Use type for Unions (string | number), primitives, or tuples.

In Part 8, we will dive deeper into technical differences, but for now, stick with this.

Try it yourself!

Let’s put what you’ve learned to the test. You need to define an interface and create a specific object to pass the hidden validation.

Exercise Requirements:

  1. Define an interface called VideoGame with:
    • title (string)
    • year (number)
    • platform (optional, string)
  2. Create a constant object called favoriteGame that implements this interface.
  3. The data must be exactly: “The Legend of Zelda”, year 1986.

In Part 4, we’ll see what happens when we have many identical objects… that is, Arrays.