API Integration in TypeScript
Level: Beginner to Intermediate
- What API Integration in TypeScript means in React + TypeScript
- How type safety improves React components
- How to model School Management System data with interfaces and types
- Common TypeScript mistakes to avoid
- How to explain this topic in interviews
Why This Matters
API Integration in TypeScript helps you build React screens with fewer runtime bugs. In real .NET Web API projects, TypeScript makes API DTOs, component props, form state, and shared data contracts easier to understand and safer to change.
Fully typed API calls prevent runtime errors and improve IDE autocomplete.
Prerequisite: Read React JS article 12 first.
The Problem
React JavaScript can fail at runtime when props, API responses, or form values have the wrong shape. This lesson shows how API Integration in TypeScript uses TypeScript to catch many of those mistakes while you write code, before the student dashboard reaches users.
Generic API Response Type
interface ApiResponse<T> {
success: boolean;
data: T;
message?: string;
errors?: Record<string, string>;
}
async function fetchStudents(): Promise<Student[]> {
const response = await fetch('/api/students');
const result: ApiResponse<Student[]> = await response.json();
if (!result.success) {
throw new Error(result.message || 'Failed to fetch');
}
return result.data;
}
Typed API Service Class
class StudentService {
private baseUrl = '/api/students';
async getAll(): Promise<Student[]> {
const response = await fetch(this.baseUrl);
if (!response.ok) throw new Error('Failed to fetch');
const result: ApiResponse<Student[]> = await response.json();
return result.data;
}
async getById(id: number): Promise<Student> {
const response = await fetch(`${this.baseUrl}/${id}`);
if (!response.ok) throw new Error('Not found');
const result: ApiResponse<Student> = await response.json();
return result.data;
}
async create(data: Omit<Student, 'id'>): Promise<Student> {
const response = await fetch(this.baseUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
if (!response.ok) throw new Error('Failed to create');
const result: ApiResponse<Student> = await response.json();
return result.data;
}
async update(id: number, data: Partial<Student>): Promise<Student> {
const response = await fetch(`${this.baseUrl}/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
if (!response.ok) throw new Error('Failed to update');
const result: ApiResponse<Student> = await response.json();
return result.data;
}
async delete(id: number): Promise<void> {
const response = await fetch(`${this.baseUrl}/${id}`, {
method: 'DELETE'
});
if (!response.ok) throw new Error('Failed to delete');
}
}
Typed Hook for API Calls
interface UseAsyncState<T> {
data: T | null;
loading: boolean;
error: Error | null;
}
function useStudentApi<T>(
apiFn: () => Promise<T>,
deps?: React.DependencyList
): UseAsyncState<T> {
const [state, setState] = useState<UseAsyncState<T>>({
data: null,
loading: true,
error: null
});
useEffect(() => {
let isMounted = true;
apiFn()
.then(data => {
if (isMounted) setState({ data, loading: false, error: null });
})
.catch(error => {
if (isMounted) {
const err = error instanceof Error ? error : new Error('Unknown');
setState({ data: null, loading: false, error: err });
}
});
return () => {
isMounted = false;
};
}, deps);
return state;
}
// Usage
function StudentList() {
const { data: students, loading, error } = useStudentApi(
() => new StudentService().getAll(),
[]
);
if (loading) return <p>Loading...</p>;
if (error) return <p>{error.message}</p>;
return (
<ul>
{students?.map(s => <li key={s.id}>{s.name}</li>)}
</ul>
);
}
Environment Types
interface ImportMetaEnv {
readonly VITE_API_BASE: string;
readonly VITE_ENV: 'development' | 'production';
}
const API_BASE: string = import.meta.env.VITE_API_BASE;
Key Takeaways
- Generic ApiResponse type
- Typed service classes
- Custom hooks for API
- Error checking
- Environment types
- Next: Routing with types
- No type on response — data could be any
- Not checking ok — Status 404 doesn't error
- No error handling — Component crashes
- Hardcoded URLs — Can't change env
import axios from 'axios';
const response = await axios.get<Student>('/api/students/1');
// Type is inferred: AxiosResponse<Student>
Use ChatGPT, Claude, or Copilot to go deeper on Typed APIs. Try these prompts:
"Why use generic ApiResponse<T>?""How do you type API services?""When should you create a custom API hook?""Quiz me on API types"
💡 Tip: After reading this article, paste your own code into AI and ask "What could go wrong here and why?" — fastest way to find edge cases and deepen understanding.
Quick Definitions
- API Integration in TypeScript - The main React + TypeScript concept explained in this lesson.
- Type/interface - A contract that describes the shape of data.
- Typed props/state - React data with clear compile-time expectations.
- API DTO - The request or response shape shared with ASP.NET Core Web API.
Common Mistakes
- Using
anytoo quickly instead of defining a useful type - Typing props loosely and losing the benefit of TypeScript
- Forgetting that API data can still be missing or invalid at runtime
- Making types too complex before the component is stable
- Not sharing clear DTO shapes between frontend and backend teams
Practice Task
Create a small React TypeScript example using API Integration in TypeScript. Keep it connected to a School Management System scenario.
Suggested practice:
- Define a clear
Student,Teacher, orAttendancetype. - Build a small typed component or hook.
- Add one valid example and one intentionally wrong example to see TypeScript errors.
- Explain the type contract in your own words.
- Rebuild the same example once without looking at the article.
Quick Revision
| Question | Answer |
|---|---|
| What is the main idea? | Use TypeScript to make API Integration in TypeScript safer in React. |
| Where is it used? | Props, state, forms, API responses, context, hooks, and routes. |
| What should beginners avoid? | Overusing any and ignoring runtime API validation. |
| What is the best debugging habit? | Read the TypeScript error, check the data shape, and fix the type contract. |
API Integration in TypeScript is a React + TypeScript concept that improves safety and maintainability. I would explain which values need types, how TypeScript catches mistakes early, and how it helps when consuming ASP.NET Core Web API responses.
It is used in typed props, API response models, form state, route parameters, context values, custom hooks, and reusable UI components.