When a React Native application receives JSON data from a REST API, TypeScript interfaces can describe the structure of that data. This helps us write safer and easier-to-understand API code.
An interface defines the expected structure of an object.
interface Student {
id: number;
name: string;
email: string;
}
This means a Student object should contain an ID, name, and email.
API interfaces provide several benefits:
interface Student {
id: number;
name: string;
email: string;
mobile: string;
}
This interface can represent a student returned by a REST API.
Suppose the PHP API returns:
{
"id": 101,
"name": "Rahul Kumar",
"email": "rahul@example.com",
"mobile": "9876543210"
}
The matching TypeScript interface is:
interface Student {
id: number;
name: string;
email: string;
mobile: string;
}
API fields containing text can be defined as string.
interface Student {
name: string;
email: string;
mobile: string;
}
TypeScript will expect these properties to contain string values.
Numeric API fields can use the number type.
interface Student {
id: number;
age: number;
fee: number;
}
Use the type that matches the data returned by your API.
Boolean API values can be represented using boolean.
interface Student {
id: number;
name: string;
active: boolean;
}
The API may return true or false.
Sometimes an API property may not always be present.
Use ? to make an interface property optional.
interface Student {
id: number;
name: string;
email?: string;
}
Here, email may or may not be included.
Some APIs return null for fields that do not have a value.
interface Student {
id: number;
name: string;
photo: string | null;
}
The photo can either be a string or null.
An API often returns multiple records as an array.
interface Student {
id: number;
name: string;
}
const students: Student[] = [];
Student[] means an array containing Student objects.
Many APIs return an object containing a success message and data.
interface StudentResponse {
success: boolean;
message: string;
data: Student[];
}
This interface describes the complete response structure.
A PHP REST API might return:
{
"success": true,
"message": "Students fetched successfully",
"data": [
{
"id": 1,
"name": "Amit",
"email": "amit@example.com"
},
{
"id": 2,
"name": "Priya",
"email": "priya@example.com"
}
]
}
API responses can contain nested objects.
interface Course {
id: number;
name: string;
}
interface Student {
id: number;
name: string;
course: Course;
}
The course property contains another object.
{
"id": 1,
"name": "Rahul",
"course": {
"id": 10,
"name": "React Native"
}
}
The nested course object can be represented by the
Course interface.
Axios can be given a TypeScript response type.
const response =
await api.get<StudentResponse>("/students");
console.log(response.data);
TypeScript now knows the expected structure of the API response.
const response =
await api.get<StudentResponse>("/students");
const students = response.data.data;
students.forEach(student => {
console.log(student.name);
});
TypeScript understands that each item is a Student.
React Native state can also use the Student interface.
const [students, setStudents] =
useState<Student[]>([]);
This tells TypeScript that the state contains an array of students.
<FlatList
data={students}
keyExtractor={item => item.id.toString()}
renderItem={({ item }) => (
<Text>{item.name}</Text>
)}
/>
Because the data is typed as Student[], the
item object is understood as a Student.
A paginated API can include metadata along with the records.
interface StudentResponse {
success: boolean;
data: Student[];
meta: {
page: number;
limit: number;
total: number;
totalPages: number;
};
}
API errors can also be represented using interfaces.
interface ApiError {
success: boolean;
message: string;
errors?: {
[key: string]: string[];
};
}
This helps the application handle structured validation errors.
A login API commonly returns a token and user information.
interface LoginResponse {
success: boolean;
message: string;
token: string;
user: {
id: number;
name: string;
email: string;
};
}
Interfaces can also describe data sent to the API.
interface LoginRequest {
email: string;
password: string;
}
This interface describes the JSON body expected by the login endpoint.
const loginData: LoginRequest = {
email: "user@example.com",
password: "123456"
};
const response =
await api.post<LoginResponse>(
"/login",
loginData
);
console.log(response.data.token);
We can create a separate interface for data sent while creating a student.
interface CreateStudentRequest {
name: string;
email: string;
mobile: string;
courseId: number;
}
The interface can be used with an Axios POST request.
Using any removes much of TypeScript's type checking.
// Avoid when possible
const data: any = response.data;
Prefer a specific interface:
const response =
await api.get<StudentResponse>("/students");
This gives better type safety.
The PHP backend produces JSON, while TypeScript interfaces describe the expected JSON structure on the React Native side.
PHP + MySQL
↓
JSON REST API
↓
Axios
↓
TypeScript Interface
↓
React Native UI
Both sides should agree on the API response structure.
The interface should represent the actual API contract.
interface Student {
id: number;
name: string;
email: string;
mobile: string;
courseId: number;
courseName?: string;
photo: string | null;
}
interface StudentResponse {
success: boolean;
message: string;
data: Student[];
}
interface CreateStudentRequest {
name: string;
email: string;
mobile: string;
courseId: number;
}
interface Student {
id: number;
name: string;
email: string;
mobile: string;
}
interface StudentResponse {
success: boolean;
message: string;
data: Student[];
}
const loadStudents = async () => {
try {
const response =
await api.get<StudentResponse>(
"/students"
);
console.log(response.data.data);
} catch (error) {
console.log("Unable to load students");
}
};
Axios now knows that the expected response follows the
StudentResponse structure.
import React, { useEffect, useState } from "react";
import { View, Text, FlatList } from "react-native";
import api from "./api";
interface Student {
id: number;
name: string;
email: string;
mobile: string;
}
interface StudentResponse {
success: boolean;
message: string;
data: Student[];
}
const StudentList = () => {
const [students, setStudents] =
useState<Student[]>([]);
useEffect(() => {
const loadStudents = async () => {
try {
const response =
await api.get<StudentResponse>(
"/students"
);
setStudents(response.data.data);
} catch (error) {
console.log(error);
}
};
loadStudents();
}, []);
return (
<View>
<FlatList
data={students}
keyExtractor={item =>
item.id.toString()
}
renderItem={({ item }) => (
<View>
<Text>{item.name}</Text>
<Text>{item.email}</Text>
<Text>{item.mobile}</Text>
</View>
)}
/>
</View>
);
};
export default StudentList;
Here, the PHP REST API returns JSON, Axios receives the response, and TypeScript uses interfaces to describe the returned data.
string, number, and boolean according to the API data.? for optional properties.null in a union when an API field can return null.Student[] for an array of Student objects.Question: Which TypeScript syntax represents an array of Student objects?