React Native allows developers to build mobile applications using React concepts. TypeScript can be used with React Native to add static typing to components, props, state, functions, navigation, API responses, forms, and reusable application logic.
TypeScript in React Native means writing React Native application code using TypeScript instead of plain JavaScript.
const message: string =
"Hello React Native";
TypeScript can type variables, functions, components, props, state, and many other parts of an application.
React Native components receive props and values that can be checked with TypeScript.
import {
View,
Text
} from "react-native";
function App() {
return (
<View>
<Text>
Hello React Native
</Text>
</View>
);
}
React Native TypeScript projects commonly use
.ts files for TypeScript logic and
.tsx files when JSX is included.
App.tsx
Student.ts
StudentScreen.tsx
api.ts
Components containing JSX are normally written using the
.tsx extension.
import {
View,
Text
} from "react-native";
function App(): React.JSX.Element {
return (
<View>
<Text>
Welcome
</Text>
</View>
);
}
export default App;
interface UserProps {
name: string;
age: number;
}
function User({
name,
age
}: UserProps): React.JSX.Element {
return (
<View>
<Text>{name}</Text>
<Text>Age: {age}</Text>
</View>
);
}
<User
name="Rahul"
age={20}
/>
TypeScript checks that the supplied props match the
UserProps interface.
const [name, setName] =
useState<string>("");
const [count, setCount] =
useState<number>(0);
const [active, setActive] =
useState<boolean>(false);
TypeScript can explicitly define the type of React Native component state.
import {
TextInput
} from "react-native";
const [name, setName] =
useState<string>("");
return (
<TextInput
value={name}
onChangeText={setName}
placeholder="Enter name"
/>
);
The onChangeText callback receives the new
text value as a string.
import {
Button
} from "react-native";
const handlePress = (): void => {
console.log("Button pressed");
};
return (
<Button
title="Save"
onPress={handlePress}
/>
);
The function does not return a value, so it can be typed
as void.
React Native's View is used to create
containers for other components.
import {
View,
Text
} from "react-native";
function Profile(): React.JSX.Element {
return (
<View>
<Text>
Student Profile
</Text>
</View>
);
}
import {
StyleSheet
} from "react-native";
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20
},
title: {
fontSize: 24
}
});
React Native's StyleSheet.create() helps
organize component styles.
interface Student {
id: number;
name: string;
}
const students: Student[] = [
{
id: 1,
name: "Rahul"
},
{
id: 2,
name: "Amit"
}
];
The Student[] type ensures that every item
follows the student structure.
import {
FlatList,
Text
} from "react-native";
interface Student {
id: number;
name: string;
}
interface Props {
students: Student[];
}
function StudentList({
students
}: Props): React.JSX.Element {
return (
<FlatList
data={students}
keyExtractor={(item) =>
item.id.toString()
}
renderItem={({ item }) => (
<Text>
{item.name}
</Text>
)}
/>
);
}
interface Student {
id: number;
name: string;
course: string;
}
const [students, setStudents] =
useState<Student[]>([]);
The interface describes the expected structure of each API student object.
useEffect(() => {
const loadStudents = async () => {
const response =
await fetch("/api/students");
const data: Student[] =
await response.json();
setStudents(data);
};
loadStudents();
}, []);
const [loading, setLoading] =
useState<boolean>(true);
const [error, setError] =
useState<string | null>(null);
These states can be used to display loading and error messages while API data is being loaded.
React Navigation can be combined with TypeScript to define screen names and route parameters.
type RootStackParamList = {
Home: undefined;
Details: {
studentId: number;
};
};
This type describes the available routes and their parameters.
type RootStackParamList = {
Home: undefined;
Details: {
studentId: number;
};
};
type DetailsScreenProps = {
route: {
params: {
studentId: number;
};
};
};
The studentId parameter is required to be a
number.
interface StudentCardProps {
name: string;
course: string;
}
function StudentCard({
name,
course
}: StudentCardProps): React.JSX.Element {
return (
<View>
<Text>
{name}
</Text>
<Text>
{course}
</Text>
</View>
);
}
interface User {
id: number;
name: string;
email: string;
mobile: string;
}
const user: User = {
id: 101,
name: "Rahul",
email: "rahul@example.com",
mobile: "9876543210"
};
Interfaces are useful for keeping user-related data consistent across multiple screens.
interface LoginForm {
email: string;
password: string;
}
const [form, setForm] =
useState<LoginForm>({
email: "",
password: ""
});
A form interface makes the structure of the form state clear.
const [email, setEmail] =
useState<string>("");
const [password, setPassword] =
useState<string>("");
return (
<View>
<TextInput
value={email}
onChangeText={setEmail}
placeholder="Email"
/>
<TextInput
value={password}
onChangeText={setPassword}
placeholder="Password"
secureTextEntry={true}
/>
</View>
);
import AsyncStorage
from "@react-native-async-storage/async-storage";
const saveName = async (
name: string
): Promise<void> => {
await AsyncStorage.setItem(
"name",
name
);
};
TypeScript can also type functions used for local storage operations.
import axios from "axios";
interface Student {
id: number;
name: string;
course: string;
}
const getStudents = async (): Promise<Student[]> => {
const response =
await axios.get<Student[]>(
"/api/students"
);
return response.data;
};
The generic type tells TypeScript what data is expected from the Axios response.
interface User {
id: number;
name: string;
}
interface AuthContextType {
user: User | null;
login: (user: User) => void;
logout: () => void;
}
An interface can define the values and functions available through a Context.
TypeScript can also describe Redux state and actions.
interface CounterState {
value: number;
}
const initialState: CounterState = {
value: 0
};
Typed Redux state makes application-wide data easier to manage safely.
src/
│
├── components/
│ ├── Button.tsx
│ └── StudentCard.tsx
│
├── screens/
│ ├── HomeScreen.tsx
│ └── DetailsScreen.tsx
│
├── types/
│ └── student.ts
│
├── services/
│ └── api.ts
│
├── navigation/
│ └── AppNavigator.tsx
│
└── App.tsx
Separating components, screens, types, services, and navigation can make a growing project easier to organize.
import {
useEffect,
useState
} from "react";
import {
View,
Text,
TextInput,
Button,
StyleSheet
} from "react-native";
interface Student {
id: number;
name: string;
course: string;
}
function App(): React.JSX.Element {
const [name, setName] =
useState<string>("");
const [students, setStudents] =
useState<Student[]>([]);
const [loading, setLoading] =
useState<boolean>(false);
const addStudent = (): void => {
if (!name.trim()) {
return;
}
const student: Student = {
id: students.length + 1,
name: name,
course: "React Native"
};
setStudents(previousStudents => [
...previousStudents,
student
]);
setName("");
};
useEffect(() => {
console.log(
"Student count:",
students.length
);
}, [students]);
return (
<View style={styles.container}>
<Text style={styles.title}>
Student Management
</Text>
<TextInput
style={styles.input}
value={name}
onChangeText={setName}
placeholder="Enter student name"
/>
<Button
title="Add Student"
onPress={addStudent}
disabled={loading}
/>
{students.map(student => (
<View
key={student.id}
style={styles.card}
>
<Text>
ID: {student.id}
</Text>
<Text>
Name: {student.name}
</Text>
<Text>
Course: {student.course}
</Text>
</View>
))}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
paddingTop: 60
},
title: {
fontSize: 24,
fontWeight: "bold",
marginBottom: 20
},
input: {
borderWidth: 1,
padding: 10,
marginBottom: 15
},
card: {
padding: 15,
marginTop: 10,
borderWidth: 1
}
});
export default App;
This example combines TypeScript interfaces,
useState, useEffect,
TextInput, Button, typed
functions, arrays, React Native components, and
StyleSheet.
.tsx files for TypeScript components containing JSX.useState can be explicitly typed.TextInput and Button have their own event APIs.Question: Which file extension is commonly used for a React Native TypeScript component containing JSX?