Types are a core feature of TypeScript, helping you write code that is safer, more predictable, and easier to debug. This guide will introduce you to the various types available in TypeScript, from basic types to advanced concepts like union types, literal types, and generics. We’ll also provide real-world examples to illustrate how TypeScript types can be applied in practical scenarios.
TypeScript is a statically typed language, meaning that variables, parameters, and return values have defined types, which can be checked at compile-time. Types make it easier to catch errors early, improving code quality and making it more reliable. In this guide, we’ll cover everything you need to know about TypeScript types, from fundamental concepts to advanced features.
Types define the kind of values a variable, function parameter, or return value can hold. They enable TypeScript to enforce type-checking rules, reducing the chances of runtime errors and making your code easier to understand and maintain. TypeScript’s type system includes basic types, advanced types, function types, and more, giving you flexibility and control over how data is handled in your code.
TypeScript includes several basic types that you’ll encounter frequently in your code.
number
The number
type represents numeric values. TypeScript doesn’t differentiate between integers and floating-point numbers.
let age: number = 25;
let salary: number = 50000.75;
string
The string
type represents text values enclosed in quotes ('
, "
, or `
).
let name: string = "Alice";
let message: string = `Hello, ${name}!`;
boolean
The boolean
type represents true or false values.
let isActive: boolean = true;
let hasPermission: boolean = false;
array
An array
type can hold a collection of values of a specific type. In TypeScript, you can declare arrays in two ways: type[]
or Array<type>
.
let numbers: number[] = [1, 2, 3];
let fruits: Array<string> = ["apple", "banana", "cherry"];
tuple
A tuple
is a fixed-length array with specific types for each position. Tuples are particularly useful for representing structured data.
let person: [string, number];
person = ["Alice", 30];
enum
An enum
(enumeration) is a way to define a set of named constants, making your code more readable.
enum Direction {
North,
South,
East,
West,
}
let travelDirection: Direction = Direction.North;
any
The any
type can hold any value, disabling type-checking for that variable. Use any sparingly, as it reduces the benefits of TypeScript’s type system.
let data: any = "Hello";
data = 42; // No error, but be cautious using `any`
Union types allow a variable to hold more than one type, increasing flexibility while maintaining type safety.
let id: string | number;
id = "ABC123";
id = 456;
Intersection types combine multiple types into one, allowing a variable to satisfy multiple type requirements.
interface Person {
name: string;
}
interface Employee {
employeeId: number;
}
type Worker = Person & Employee;
let employee: Worker = {
name: "Alice",
employeeId: 101,
};
Literal types allow you to specify exact values for a variable, making it useful for cases where you want to restrict a variable to specific options.
let alignment: "left" | "right" | "center";
alignment = "left"; // Valid
// alignment = "up"; // Error
Type aliases let you create custom names for complex types, improving code readability and reusability.
Copy code
type Point = {
x: number;
y: number;
};
let coordinates: Point = { x: 10, y: 20 };
TypeScript has a type inference feature, which automatically detects the type of a variable based on its initial value.
let inferredValue = 42; // Inferred as `number`
TypeScript allows you to define types for function parameters and return values, improving clarity and type safety.
function add(a: number, b: number): number {
return a + b;
}
In this example, a
and b
are number
types, and the function is expected to return a number
. If you try to pass a non-number argument, TypeScript will throw an error.
Parameters can be marked as optional using ?
, or you can provide a default value.
function greet(name: string, greeting: string = "Hello"): string {
return `${greeting}, ${name}`;
}
In TypeScript, you can define objects with specific types for each property. This helps ensure that objects have the correct structure.
let user: { name: string; age: number } = { name: "Alice", age: 25 };
Interfaces allow you to define the structure of an object, providing consistency across your code.
interface User {
name: string;
age: number;
}
let user: User = { name: "Alice", age: 30 };
Interfaces are often used in TypeScript to describe the shape of data and enforce consistency across objects.
Generics allow you to write functions and classes that work with various types without losing type safety.
function identity<T>(value: T): T {
return value;
}
let result1 = identity<number>(10);
let result2 = identity<string>("Hello");
Generics are denoted by <T>
(or any other letter) and allow the function to operate on different types while maintaining type safety.
class Box<T> {
contents: T;
constructor(contents: T) {
this.contents = contents;
}
}
let numberBox = new Box<number>(123);
let stringBox = new Box<string>("Hello");
Let’s say you’re building an e-commerce app where each product has a name, price, and optional discount. You can use an interface to define the product type.
interface Product {
name: string;
price: number;
discount?: number;
}
function displayProduct(product: Product): void {
console.log(`Product: ${product.name}`);
console.log(`Price: $${product.price}`);
if (product.discount) {
console.log(`Discount: ${product.discount}%`);
}
}
let product1: Product = { name: "Laptop", price: 1200, discount: 10 };
displayProduct(product1);
Generics are useful for building reusable code, such as a data fetcher that can work with various data types.
async function fetchData<T>(url: string): Promise<T> {
const response = await fetch(url);
return response.json() as T;
}
interface User {
id: number;
name: string;
}
fetchData<User>("https://api.example.com/user/1").then((user) => {
console.log(`User: ${user.name}`);
});
In this example, the fetchData
function uses generics to specify that the data it returns matches the User
interface, providing type safety while fetching data.
number
, string
, boolean
, and array
, are fundamental for all TypeScript code.Types are at the heart of TypeScript, providing structure and safety that make your code more reliable. This guide has covered basic types, advanced types, function and object types, and generics, showing how each can be used to create safer, more maintainable code. By understanding TypeScript’s type system, you’ll be able to write code that is easier to debug, more predictable, and better suited for large-scale applications. Start exploring these types in your projects and see how TypeScript can improve your coding experience!