-m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install fastapi uvicorn pydantic
Enter fullscreen mode Exit fullscreen mode
Create a file named `main.py` with a basic AI API endpoint. We’ll define Pydantic models for the request and response to match our AI payload structure:
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional
app = FastAPI()
class AIRequest(BaseModel):
prompt: str
max_tokens: Optional[int] = 256
temperature: Optional[float] = 0.7
model: Optional[str] = "mock-gpt-3.5"
class AIResponse(BaseModel):
generated_text: str
model: str
tokens_used: int
latency_ms: float
Mock AI generation function (replace with real model integration as needed)
def mock_generate_text(request: AIRequest) -> AIResponse:
return AIResponse(
generated_text=f"Mock response to: {request.prompt}",
model=request.model,
tokens_used=len(request.prompt.split()) * 2,
latency_ms=120.5
)
@app.post("/api/ai/generate", response_model=AIResponse)
async def generate_text(request: AIRequest):
return mock_generate_text(request)
Enter fullscreen mode Exit fullscreen mode
Run the FastAPI app with:
uvicorn main:app --reload --port 8000
Enter fullscreen mode Exit fullscreen mode
**Step 2: Initialize the TypeScript Project**
Create a new directory for your TypeScript client, initialize a project, and install dependencies including Zod 3.23 and Axios for API calls:
mkdir ts-client && cd ts-client
npm init -y
npm install typescript@5.6 zod@3.23 axios
npm install @types/node axios --save-dev
npx tsc --init --strict --target es2022 --module node16
Enter fullscreen mode Exit fullscreen mode
TypeScript 5.6’s strict mode ensures compile-time type checking, while Zod adds runtime validation to bridge the gap between static types and dynamic API responses.
**Step 3: Define Zod Schemas for Type Safety**
Zod 3.23 lets you define schemas that double as both runtime validators and static type definitions. Create a `schema.ts` file that mirrors the Pydantic models from your FastAPI backend:
import { z } from "zod";
// Zod schema for AI request payload
export const AIRequestSchema = z.object({
prompt: z.string().min(1, "Prompt cannot be empty"),
max_tokens: z.number().int().positive().optional().default(256),
temperature: z.number().min(0).max(1).optional().default(0.7),
model: z.string().optional().default("mock-gpt-3.5")
});
// Zod schema for AI response payload
export const AIResponseSchema = z.object({
generated_text: z.string(),
model: z.string(),
tokens_used: z.number().int().positive(),
latency_ms: z.number().positive()
});
// Infer TypeScript types from Zod schemas (TypeScript 5.6 supports this natively)
export type AIRequest = z.infer;
export type AIResponse = z.infer;
Enter fullscreen mode Exit fullscreen mode
TypeScript 5.6’s improved type inference works seamlessly with Zod’s `z.infer` to generate strict, accurate types for your payloads.
**Step 4: Build a Type-Safe API Client**
Create an `api-client.ts` file that uses Axios to call your FastAPI endpoint, with Zod validation for both requests and responses:
import axios from "axios";
import { AIRequestSchema, AIResponseSchema, AIRequest, AIResponse } from "./schema";
const apiClient = axios.create({
baseURL: "http://localhost:8000/api/ai",
timeout: 5000
});
export async function generateAIContent(request: AIRequest): Promise {
// Validate request payload at runtime (optional, but useful for debugging)
const validatedRequest = AIRequestSchema.parse(request);
const response = await apiClient.post("/generate", validatedRequest);
// Validate response payload against Zod schema to ensure type safety
const validatedResponse = AIResponseSchema.parse(response.data);
return validatedResponse;
}
// Example usage with TypeScript 5.6 const type parameters
async function testEndpoint() {
try {
const result = await generateAIContent({
prompt: "Explain type safety in 2 sentences",
max_tokens: 100
});
console.log("Generated Text:", result.generated_text);
console.log("Tokens Used:", result.tokens_used);
} catch (error) {
if (error instanceof z.ZodError) {
console.error("Validation Error:", error.errors);
} else {
console.error("API Error:", error);
}
}
}
testEndpoint();
Enter fullscreen mode Exit fullscreen mode
**Step 5: Test the Integration**
Compile your TypeScript code and run the client:
npx tsc
node dist/api-client.js
Enter fullscreen mode Exit fullscreen mode
You should see the mock generated text and token count logged to the console. Try passing an invalid request (e.g., an empty prompt) to see Zod catch the validation error at runtime, and TypeScript will flag type errors at compile time if you pass incorrect payloads.
**Using TypeScript 5.6 Features for Better Safety**
TypeScript 5.6 introduces several features that enhance integration with Zod:
- **Const Type Parameters**: Use `as const` with Zod schemas to enforce stricter literal types for default values.
- **Improved Satisfies Operator**: Use `satisfies` to ensure your Zod schemas match expected type shapes without losing literal type information.
- **Strict Falsy Checks**: TypeScript 5.6 refines type checks for falsy values, reducing unintended runtime errors when handling API responses.
Example of using `satisfies` with Zod in TypeScript 5.6:
const AIRequestSchema = z.object({
prompt: z.string(),
max_tokens: z.number().optional()
}) satisfies z.ZodType;
Enter fullscreen mode Exit fullscreen mode
## Pitfall Guide
1. **Schema-Model Drift**: Pydantic and Zod schemas must be manually synchronized. Use shared JSON Schema generation, OpenAPI codegen, or automated sync scripts to prevent field mismatches between backend and client.
2. **Over-Validation in Hot Paths**: Validating every request/response adds latency. Apply Zod validation strictly at external boundaries (API gateway/client), not on internal microservice-to-microservice calls where trust is already established.
3. **Ignoring TS 5.6 `satisfies` Operator**: Failing to use `satisfies` with Zod schemas causes loss of literal types and narrows type inference. Always apply `satisfies z.ZodType` to preserve strict shapes and enable better IDE autocomplete.
4. **Async Error Handling Gaps**: Zod throws synchronously, but API calls are async. Wrap `schema.parse()` in try/catch or use `schema.safeParse()` to prevent unhandled promise rejections and ensure graceful degradation in production.
5. **Optional/Default Value Mismatches**: Pydantic’s `Optional` and Zod’s `.optional().default()` behave differently during serialization. Explicitly define defaults in both layers and test edge cases where `null` vs `undefined` propagation occurs.
6. **Strict Falsy Checks Misconfiguration**: TS 5.6’s refined falsy checks can break legacy code. Enable `strictNullChecks` and `strictFunctionTypes` in `tsconfig.json` to catch edge cases early, but audit existing codebases before upgrading to avoid unexpected type narrowing.
## Deliverables
- **Blueprint**: End-to-End Type-Safe AI API Architecture Diagram & Implementation Guide (covers FastAPI → OpenAPI → Zod schema generation → TS client integration pipeline)
- **Checklist**: Pre-deployment Type Safety Validation Checklist (schema sync verification, strict mode enforcement, validation boundary mapping, error handling audit, latency benchmarking)
- **Configuration Templates**: Production-ready `tsconfig.json`, `pyproject.toml`, `schema.ts`, `api-client.ts`, and `main.py` boilerplates with TS 5.6 strict flags, Zod 3.23 validation hooks, and FastAPI Pydantic v2 compatibility pre-configured.