
2025-08-23
React Native + TypeScript: Полное руководство по типизации
TypeScript в связке с React Native позволяет создавать надёжные мобильные приложения с строгой типизацией. В этом руководстве рассмотрим:
- Настройку TypeScript в React Native проекте
- Типизацию компонентов и пропсов
- Работу с навигацией и типами маршрутов
- Использование хуков с TypeScript
- Типизацию контекста и глобального состояния
1. Настройка TypeScript в React Native
npx react-native init MyApp --template react-native-template-typescript
Основные файлы типизации:
tsconfig.json
- конфигурация TypeScript@types/react-native
- типы React Native@types/react
- типы React
2. Типизация компонентов
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
interface ButtonProps {
title: string;
onPress: () => void;
disabled?: boolean;
}
const CustomButton: React.FC<ButtonProps> = ({
title,
onPress,
disabled = false
}) => {
return (
<View style={[styles.button, disabled && styles.disabled]}>
<Text style={styles.text} onPress={!disabled ? onPress : undefined}>
{title}
</Text>
</View>
);
};
const styles = StyleSheet.create({
button: {
padding: 15,
backgroundColor: '#007bff',
borderRadius: 5,
},
text: {
color: 'white',
textAlign: 'center',
},
disabled: {
opacity: 0.6,
}
});
export default CustomButton;
3. Типизация навигации
Для React Navigation установите типы:
npm install @react-navigation/native @react-navigation/native-stack
npm install -D @types/react-navigation
Пример типизации стековой навигации:
import { createNativeStackNavigator } from '@react-navigation/native-stack';
type RootStackParamList = {
Home: undefined;
Profile: { userId: string };
Settings: undefined;
};
const Stack = createNativeStackNavigator<RootStackParamList>();
const App = () => {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen
name="Profile"
component={ProfileScreen}
initialParams={{ userId: 'default' }}
/>
<Stack.Screen name="Settings" component={SettingsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
};
4. Типизация хуков состояния
import React, { useState, useEffect } from 'react';
import { ActivityIndicator, View, Text } from 'react-native';
interface UserData {
id: string;
name: string;
email: string;
}
const UserProfile: React.FC = () => {
const [user, setUser] = useState<UserData | null>(null);
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const fetchUser = async () => {
try {
const response = await fetch('https://api.example.com/user');
const data: UserData = await response.json();
setUser(data);
} catch (err) {
setError(err instanceof Error ? err.message : 'Ошибка загрузки');
} finally {
setLoading(false);
}
};
fetchUser();
}, []);
if (loading) return <ActivityIndicator size="large" />;
if (error) return <Text>Ошибка: {error}</Text>;
if (!user) return <Text>Пользователь не найден</Text>;
return (
<View>
<Text>{user.name}</Text>
<Text>{user.email}</Text>
</View>
);
};
5. Типизация контекста
import React, { createContext, useContext, useReducer } from 'react';
type Theme = 'light' | 'dark';
interface ThemeContextType {
theme: Theme;
toggleTheme: () => void;
}
const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
const themeReducer = (state: Theme): Theme =>
state === 'light' ? 'dark' : 'light';
export const ThemeProvider: React.FC = ({ children }) => {
const [theme, dispatch] = useReducer(themeReducer, 'light');
const toggleTheme = () => dispatch();
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
};
export const useTheme = () => {
const context = useContext(ThemeContext);
if (!context) {
throw new Error('useTheme must be used within ThemeProvider');
}
return context;
};
Лучшие практики TypeScript в React Native
-
Строгий режим Включите
strict: true
в tsconfig.json для максимальной проверки типов -
Типизация пропсов Всегда определяйте интерфейсы для пропсов компонентов:
interface UserCardProps {
user: User;
onPress: (userId: string) => void;
isActive?: boolean;
}
- Утилитарные типы Используйте встроенные TypeScript утилиты:
type UserPreview = Pick<User, 'id' | 'name'>;
type UserWithoutEmail = Omit<User, 'email'>;
type OptionalUser = Partial<User>;
- Валидация данных Используйте Zod для проверки API-ответов:
import { z } from 'zod';
const UserSchema = z.object({
id: z.string(),
name: z.string().min(2),
email: z.string().email()
});
const safeUser = UserSchema.safeParse(apiResponse);
- Типизация API Определяйте типы для всех API-ответов:
interface ApiResponse<T> {
data: T;
error?: string;
status: number;
}
- Интеграция с ESLint Настройте eslint-plugin-typescript для автоматической проверки:
{
"extends": [
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking"
]
}
- Обновление типов Регулярно обновляйте @types-пакеты для совместимости с версиями библиотек
Заключение
Внедрение TypeScript в React Native разработку требует начальных затрат времени, но даёт значительные преимущества:
- Снижение количества runtime-ошибок на 40-60%
- Ускорение разработки за счёт автодополнения
- Упрощение онбординга новых разработчиков
- Повышение стабильности при рефакторинге
Начните с базовой типизации компонентов и постепенно добавляйте сложные типы. Используйте приведённые примеры как основу для построения типобезопасного приложения.