TypeScript React Native-д
TypeScript бол JavaScript дээр төрлийн (type) систем нэмсэн хэл. Код бичих үед алдааг илрүүлдэг тул олон цагийн дибагнаасаа аврагддаг. Expo апп үүсгэхэд TypeScript автоматаар тохируулагдсан байдаг — бид зөвхөн хэрхэн зөв ашиглахыг сурахад л хангалттай.
Үндсэн type-ууд React Native-д
Props-т type тодорхойлох нь хамгийн түгээмэл хэрэглээ. interface эсвэл type хоёрыг ашиглаж болно:
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
// Props-н interface тодорхойлно
interface ButtonProps {
label: string;
onPress: () => void;
color?: string; // ? = заавал биш
disabled?: boolean;
size?: 'sm' | 'md' | 'lg'; // Union type — зөвхөн эдгээр утга
}
export function AppButton({
label,
onPress,
color = '#22d3ee', // Default утга
disabled = false,
size = 'md',
}: ButtonProps) {
const fontSize = size === 'sm' ? 14 : size === 'lg' ? 20 : 16;
return (
<TouchableOpacity
style={[styles.button, { backgroundColor: disabled ? '#475569' : color }]}
onPress={onPress}
disabled={disabled}
>
<Text style={[styles.label, { fontSize }]}>{label}</Text>
</TouchableOpacity>
);
}
const styles = StyleSheet.create({
button: { paddingVertical: 12, paddingHorizontal: 24, borderRadius: 10, alignItems: 'center' },
label: { color: '#0b1120', fontWeight: 'bold' },
});
Navigation type-ууд
React Navigation ашиглаж байгаа бол route params-т type нэмэх нь маш чухал — алдааг эрт гаргаж өгдөг:
import { NativeStackScreenProps } from '@react-navigation/native-stack';
// Бүх screen-н params-г нэг дор тодорхойлно
type RootStackParamList = {
Home: undefined; // params байхгүй
CourseDetail: { slug: string; isFree: boolean };
LessonDetail: { courseSlug: string; lessonSlug: string; order: number };
Profile: { userId?: string }; // заавал биш param
};
// Screen component props автоматаар type авна
type CourseDetailProps = NativeStackScreenProps<RootStackParamList, 'CourseDetail'>;
export default function CourseDetailScreen({ route, navigation }: CourseDetailProps) {
// route.params.slug — TypeScript мэднэ, autocomplete ажиллана
const { slug, isFree } = route.params;
function goToLesson(lessonSlug: string) {
navigation.navigate('LessonDetail', {
courseSlug: slug,
lessonSlug,
order: 1,
});
}
return (
<View style={{ flex: 1, backgroundColor: '#0b1120', padding: 20 }}>
<Text style={{ color: '#f1f5f9', fontSize: 24 }}>{slug}</Text>
{isFree && <Text style={{ color: '#4ade80' }}>Үнэгүй</Text>}
</View>
);
}
Custom hook-д TypeScript
Hook-ийн буцаах утгыг тодорхой зааж өгөх нь ашиглах талаас нь ойлгомжтой болгодог:
import { useState, useEffect } from "react";
interface Lesson {
slug: string;
title: string;
order: number;
completed: boolean;
}
interface UseLessonsReturn {
lessons: Lesson[];
loading: boolean;
error: string | null;
refetch: () => void;
}
// Generic ашигласнаар дурын өгөгдлийн төрлийг дэмжих hook
function useFetch<T>(url: string): {
data: T | null;
loading: boolean;
error: string | null;
} {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
fetch(url)
.then((res) => {
if (!res.ok) throw new Error("Сервер алдаа гарлаа");
return res.json() as Promise<T>;
})
.then(setData)
.catch((err: Error) => setError(err.message))
.finally(() => setLoading(false));
}, [url]);
return { data, loading, error };
}
// Ашиглах
export function useLessons(courseSlug: string): UseLessonsReturn {
const { data, loading, error } = useFetch<Lesson[]>(
`https://api.example.com/courses/${courseSlug}/lessons`,
);
function refetch() {
// дахин fetch хийх логик
}
return {
lessons: data ?? [],
loading,
error,
refetch,
};
}
AsyncStorage ба Supabase-тай TypeScript
Third-party library-тай ажиллахад type annotation нэмэх нь алдааг бууруулдаг:
import AsyncStorage from "@react-native-async-storage/async-storage";
// Generic функц — хадгалах өгөгдлийн төрлийг caller тодорхойлно
async function saveData<T>(key: string, value: T): Promise<void> {
try {
await AsyncStorage.setItem(key, JSON.stringify(value));
} catch (error) {
console.error("Хадгалах алдаа:", error);
}
}
async function loadData<T>(key: string): Promise<T | null> {
try {
const raw = await AsyncStorage.getItem(key);
return raw ? (JSON.parse(raw) as T) : null;
} catch {
return null;
}
}
// Хэрэглэх — TypeScript автоматаар төрлийг мэднэ
interface UserSettings {
theme: "dark" | "light";
language: "mn" | "en";
fontSize: number;
}
await saveData<UserSettings>("settings", {
theme: "dark",
language: "mn",
fontSize: 16,
});
const settings = await loadData<UserSettings>("settings");
// settings?.theme → TypeScript: 'dark' | 'light' гэдгийг мэднэ
TypeScript эхэндээ нэмэлт ажил мэт санагддаг боловч апп томорч, баг гишүүд нэмэгдэх тусам асар их цаг хугацаа хэмнэдэг. Өнөөдрөөс дадал болгоорой!
Дараагийн хичээлд:
Тест бичих (Jest + RNTL) — аппынхаа component, hook, логикийг автоматаар шалгах тест бичих аргыг сурна. Тест нь "ажиллаж байна" гэдгийг баталгаажуулах хамгийн найдвартай арга.