In TypeScript, an object is a collection of key - value pairs. Just like in JavaScript, objects can hold various types of data such as numbers, strings, booleans, and even other objects. However, TypeScript allows us to explicitly define the types of these properties.
// Defining an object with explicit types
const person: { name: string; age: number } = {
name: 'John Doe',
age: 30
};
An interface in TypeScript is a way to define a contract for an object’s structure. It specifies the names and types of the properties that an object must have. Interfaces do not contain any implementation; they only describe the shape of an object.
// Defining an interface
interface Person {
name: string;
age: number;
}
// Using the interface to define an object
const person: Person = {
name: 'Jane Smith',
age: 25
};
We can define objects by directly specifying the types of their properties. This is useful for simple objects or when we don’t need to reuse the type definition.
const car: { make: string; model: string; year: number } = {
make: 'Toyota',
model: 'Corolla',
year: 2020
};
Interfaces are great for defining reusable object shapes. We can use an interface to enforce a certain structure on multiple objects.
interface Book {
title: string;
author: string;
pages: number;
}
const book1: Book = {
title: 'The Great Gatsby',
author: 'F. Scott Fitzgerald',
pages: 180
};
const book2: Book = {
title: 'To Kill a Mockingbird',
author: 'Harper Lee',
pages: 281
};
Sometimes, a property may not be required for an object. We can mark a property as optional in an interface using the ?
symbol.
interface Employee {
name: string;
age: number;
department?: string;
}
const employee1: Employee = {
name: 'Bob',
age: 35
};
const employee2: Employee = {
name: 'Alice',
age: 28,
department: 'HR'
};
We can use the readonly
keyword to make a property in an interface immutable. Once a value is assigned to a readonly property, it cannot be changed.
interface Point {
readonly x: number;
readonly y: number;
}
const point: Point = { x: 10, y: 20 };
// This will cause a compilation error
// point.x = 30;
Interfaces can extend other interfaces, allowing us to create more complex object structures by inheriting properties from existing interfaces.
interface Shape {
color: string;
}
interface Square extends Shape {
sideLength: number;
}
const square: Square = {
color: 'blue',
sideLength: 5
};
Interfaces can also be used to define the shape of a function. A function interface describes the parameters and return type of a function.
interface Calculator {
(a: number, b: number): number;
}
const add: Calculator = (a, b) => a + b;
const subtract: Calculator = (a, b) => a - b;
Indexable interfaces allow us to define objects that can be accessed using an index, similar to arrays or maps.
interface StringArray {
[index: number]: string;
}
const myArray: StringArray = ['apple', 'banana', 'cherry'];
console.log(myArray[1]); // Output: banana
Interfaces should have a single responsibility. Avoid creating overly complex interfaces with too many properties. This makes the code more maintainable and easier to understand.
Interfaces are meant to define contracts. When passing objects between different parts of your application, use interfaces to ensure that the objects have the expected structure.
Use optional properties when a property may or may not be present in an object. Use readonly properties when you want to prevent accidental modification of a property.
Working with objects and interfaces in TypeScript is a powerful way to write more robust and maintainable code. Interfaces provide a clear contract for the structure of objects, making it easier to catch errors at compile - time. By understanding the fundamental concepts, usage methods, common practices, and best practices, developers can take full advantage of TypeScript’s static typing capabilities when dealing with objects.