When we talk about API integration in TypeScript, we rarely discuss the mystical. Usually, it’s CRUD operations, financial data, or weather forecasts. But sometimes, you want to build something a little more... esoteric.
Enter the Vedika API. It’s an AI-powered Vedic astrology service. It solves a specific problem: you feed it a question and a birth chart (date, time, location), and it generates an AI-driven insight.
For a TypeScript developer, integrating this isn't just about making a POST request. It's about rigorously defining the shape of the cosmos (and the data) before you actually ask it a question.
In this post, we’ll build a type-safe client from scratch. We’ll focus on how to structure your interfaces, handle async operations, and catch the edge cases that usually break production apps.
The Problem: The "Any" Trap
Before we write code, let’s look at the friction point. If you simply use any in TypeScript, you bypass the compiler's safety net.
// ❌ The dangerous way
async function getHoroscope(question: string) {
const res = await fetch('...');
const data = await res.json(); // TypeScript thinks data is any
return data.prediction; // 💥 Runtime crash if the API changes
}
If the API response structure shifts slightly (which happens often during AI model training), your app crashes.
The Solution: Strongly Typed Interfaces
The Vedika API has a single endpoint: POST /api/v1/astrology/query.
To make this robust, we need to define what the input looks like and what the output looks like.
1. Defining the Data Shapes
First, let's define the input structure. The API expects a question string and a birthDetails object containing date, latitude, and longitude.
// types.ts
/**
* Represents the geographic location of birth.
* Using strict number types for coordinates.
*/
interface BirthDetails {
date: string; // ISO 8601 format: YYYY-MM-DD
time: string; // ISO 8601 format: HH:mm:ss
lat: number;
lng: number;
}
/**
* The request payload for the Vedika API.
*/
interface AstrologyQueryRequest {
question: string;
birthDetails: BirthDetails;
}
/**
* The expected response structure from Vedika.
* We use 'unknown' initially to force us to handle the data explicitly.
*/
interface AstrologyResponse {
prediction: string;
planetary_positions?: Record<string, string>;
remedial_measures?: string[];
error?: string;
}
Notice we used string for dates. In JSON (which APIs communicate over), dates are rarely objects. They are serialized strings. If we tried to use a native Date object in the interface, we would have to deal with serialization logic manually every time we sent the request.
2. The Client Class
Now, let's wrap the fetch logic in a class. This encapsulates our configuration and error handling.
Top comments (0)