- TypeScript Tutorial
- TypeScript Home
- TypeScript Introduction
- TypeScript Setup
- TypeScript First Program
- TypeScript vs JavaScript
- TypeScript Data Types
- TypeScript Type Inference
- TypeScript Type Annotations
- TypeScript Interfaces
- TypeScript Enums
- TypeScript Type Aliases
- TypeScript Type Assertions
- TypeScript Variables
- TypeScript Functions
- TypeScript Functions
- TypeScript Optional Parameters
- TypeScript Default Parameters
- TypeScript Rest Parameters
- TypeScript Arrow Functions
- Classes and Objects
- Introduction to Classes
- Properties and Methods
- Access Modifiers
- Static Members
- Inheritance
- Abstract Classes
- Interfaces vs Classes
- Advanced Types
- TypeScript Union Types
- TypeScript Intersection Types
- TypeScript Literal Types
- TypeScript Nullable Types
- TypeScript Type Guards
- TypeScript Discriminated Unions
- TypeScript Index Signatures
- TypeScript Generics
- Introduction to Generics
- TypeScript Generic Functions
- TypeScript Generic Classes
- TypeScript Generic Constraints
- TypeScript Modules
- Introduction to Modules
- TypeScript Import and Export
- TypeScript Default Exports
- TypeScript Namespace
- Decorators
- Introduction to Decorators
- TypeScript Class Decorators
- TypeScript Method Decorators
- TypeScript Property Decorators
- TypeScript Parameter Decorators
- Configuration
- TypeScript tsconfig.json File
- TypeScript Compiler Options
- TypeScript Strict Mode
- TypeScript Watch Mode
TypeScript Interfaces
In TypeScript, an interface acts as a powerful "contract" for your code. It defines the exact shape that an object must follow, specifying which properties it should have, their data types, and whether they are required or optional. By using interfaces, you shift your error checking from "runtime" (when the app is already running for a user) to "compile-time" (while you are still writing the code).
Why Use Interfaces?
- Consistency: Ensure every developer on your team uses the same structure for shared data like Users, Products, or API responses.
- Tooling Support: Interfaces enable modern editors like VS Code to provide "IntelliSense" (autocomplete suggestions), which speeds up development significantly.
- Documentation: An interface serves as living documentation. By looking at an interface, you immediately understand what an object represents without digging through logic.
- Scalability: Interfaces make it easier to refactor large codebases because TypeScript will instantly highlight every file that needs updating if the interface changes.
Defining an Interface
You can define an interface using the interface keyword. By convention, interface names should start with a capital letter (PascalCase).
interface Person {
name: string;
age: number;
isStudent: boolean;
}
let person1: Person = {
name: "John",
age: 25,
isStudent: true
};
console.log(person1.name, person1.age);
Data, use specific names like UserProfile or AuthResponse.
Optional Properties
Sometimes, an object might not have all the fields defined in an interface. For example, a user might choose not to provide their phone number. You can mark a property as optional by adding a ? after the property name.
interface Person {
name: string;
age?: number; // age is now optional
}
let person2: Person = {
name: "Alice"
};
console.log(person2.name); // Works perfectly
undefined. Always check if the value exists before performing operations on it (e.g., if (person2.age) { ... }).
Read-Only Properties
There are scenarios where you want a property to be set only when the object is first created and never changed again. The readonly modifier ensures immutability for specific properties.
interface Car {
readonly vin: string; // Vehicle Identification Number should never change
model: string;
year: number;
}
let myCar: Car = {
vin: "123-XYZ-990",
model: "Tesla",
year: 2023
};
myCar.year = 2024; // Allowed: You might upgrade parts.
// myCar.vin = "456-ABC"; // Error: Cannot assign to 'vin' because it is a read-only property.
readonly with const. Use const for variables and readonly for properties within an interface or class.
Function Types
Interfaces aren't just for data objects; they can also describe the "signature" of a function. This is particularly useful for defining callbacks or mathematical operations.
interface MathOp {
(val1: number, val2: number): number;
}
let add: MathOp = (x, y) => x + y;
let multiply: MathOp = (x, y) => x * y;
console.log(add(10, 20)); // Output: 30
Interface with Arrays
You can use interfaces to define objects that can be indexed, much like an array. This is known as an "Index Signature."
interface StringArray {
[index: number]: string;
}
let names: StringArray = ["Alice", "Bob", "Charlie"];
console.log(names[0]); // Output: Alice
Extending Interfaces
One of the best features of interfaces is their ability to inherit from others. This follows the DRY (Don't Repeat Yourself) principle, allowing you to build complex types from simpler ones.
interface User {
username: string;
email: string;
}
// Employee inherits all properties from User and adds its own
interface Employee extends User {
employeeId: number;
department: string;
}
let developer: Employee = {
username: "dev_pro",
email: "[email protected]",
employeeId: 101,
department: "Engineering"
};
interface Manager extends User, Employee { ... }.
Interface for Classes
Interfaces can be used as a template for classes. When a class implements an interface, it is forced to include all the properties and methods defined in that interface. This is a core concept in Object-Oriented Programming (OOP).
interface Logger {
log(message: string): void;
}
class ConsoleLogger implements Logger {
log(message: string) {
console.log("LOG:", message);
}
}
const myLogger = new ConsoleLogger();
myLogger.log("Application started!");
Intersection Types
While interfaces are typically used for object shapes, you can combine them using intersection types (&). This is useful when you want to merge two existing structures into a temporary type for a specific function.
interface HasName {
name: string;
}
interface HasContact {
email: string;
}
// Combining two interfaces into one type
type ContactCard = HasName & HasContact;
let businessCard: ContactCard = {
name: "Alice Smith",
email: "[email protected]"
};
Summary
Interfaces in TypeScript are more than just a type-checking tool; they are a fundamental part of writing clean, professional code. By leveraging optional properties for flexibility, readonly for data integrity, and extends for reusability, you create a codebase that is easier to navigate and far less prone to errors. Whether you are defining a simple object or architectural constraints for a class, interfaces are your first line of defense in building robust applications.