Typescript Foundations / Best Practices and Real World Patterns

Type Safe API Calls

Type-safe API calls ensure that your request and response data are correctly typed, making your code less error-prone and easier to maintain.


🧱 Why Type Safety Matters?

Without types:

fetch('/api/user')
  .then(res => res.json())
  .then(data => {
    console.log(data.name); // 😬 Might throw if name is undefined
  });

With types:

interface User {
  id: number;
  name: string;
  email: string;
}

fetch('/api/user')
  .then(res => res.json())
  .then((data: User) => {
    console.log(data.name); // ✅ Type-safe
  });

📦 Using Axios with Generics (Recommended)

Axios supports generics, making it great for type-safe APIs.

✅ Example

import axios from 'axios';

interface User {
  id: number;
  name: string;
  email: string;
}

const fetchUser = async () => {
  const response = await axios.get<User>('/api/user');
  return response.data;
};

Here:

  • axios.get<User> ensures the response will match the User interface.

  • You get type inference, auto-completion, and type-checking.


🧮 Typing API Parameters

You can also type request payloads:

interface LoginRequest {
  username: string;
  password: string;
}

interface LoginResponse {
  token: string;
  userId: number;
}

const login = async (credentials: LoginRequest) => {
  const response = await axios.post<LoginResponse>('/api/login', credentials);
  return response.data;
};

🔁 Reusable Typed API Client

const apiClient = axios.create({
  baseURL: '/api',
  headers: {
    'Content-Type': 'application/json',
  },
});

interface ApiResponse<T> {
  data: T;
  status: number;
}

const getTyped = async <T>(url: string): Promise<ApiResponse<T>> => {
  const res = await apiClient.get<T>(url);
  return { data: res.data, status: res.status };
};

// Usage:
interface Product {
  id: number;
  name: string;
}

const getProduct = () => getTyped<Product>('/product/1');

🧠 Summary

Feature

Benefit

Generic response typing

Type-safe response data

Interface-based input types

Prevents sending wrong payloads

Reusable API wrapper

DRY and consistent request patterns

IDE support

Autocompletion and refactoring help