React Native ve TypeScript 2026: Tip Güvenli Mimari ve Mülakat Soruları
React Native'de TypeScript ile tip güvenli mimari oluşturma: Strict API, TurboModule Codegen, React Navigation 7 tiplendirmesi ve discriminated union'lar.

React Native ekosistemi 2026'da TypeScript-first bir yapıya tamamen geçiş yapmış durumda. New Architecture'ın stabil hale gelmesiyle birlikte, TurboModules ve Fabric renderer artık compile-time tip güvenliği sunuyor. Codegen sayesinde native modüller otomatik olarak TypeScript interface'lerinden türetiliyor ve runtime hatalarının büyük kısmı build aşamasında yakalanıyor. Modern React Native projeleri strict TypeScript konfigürasyonu, tip güvenli navigasyon ve discriminated union pattern'leriyle production-ready mobil uygulamalar geliştiriyor.
2026'da Değişenler: React Native 0.76+ sürümleri varsayılan olarak TurboModules ve Fabric renderer ile geliyor. TypeScript, template projelerde artık opsiyonel değil zorunlu bir seçim. exactOptionalPropertyTypes ve noUncheckedIndexedAccess flag'leri community standartlarının parçası haline geldi.
TypeScript Neden React Native'de Varsayılan Haline Geldi
React Native'in JavaScript kökleri olmasına rağmen, ecosystem 2026 itibarıyla TypeScript'i standard olarak benimsedi. Bunun arkasında birkaç kritik neden var. İlk olarak, New Architecture'ın JSI (JavaScript Interface) üzerinden native tarafla doğrudan konuşması, tip güvenliğini zorunlu kılıyor. Eski Bridge mimarisinde JSON serializasyon hataları runtime'da ortaya çıkarken, TurboModules bu hataları compile-time'da yakalar.
İkinci olarak, React Navigation gibi temel kütüphaneler TypeScript-first API'ler sunuyor. Stack navigator'da bir ekrana yanlış parametre göndermek, kod yazarken hata veriyor. Üçüncü olarak, Metro bundler'ın performans iyileştirmeleri sayesinde TypeScript transpile süresi artık production build'lerde ihmal edilebilir seviyede. Son olarak, team scalability açısından TypeScript, cross-platform mobil projelerde kod kalitesini ve maintainability'yi önemli ölçüde artırıyor.
Bu faktörler birleşince, TypeScript React Native projelerinde "nice to have" olmaktan çıkıp "must-have" haline geldi. Expo ve React Native CLI'nın varsayılan template'leri artık TypeScript ile geliyor ve community'nin büyük çoğunluğu bu standarda geçiş yaptı.
Strict TypeScript Konfigürasyonu ile Başlamak
Modern React Native projelerinde strict: true yeterli değil. 2026 standartları, exactOptionalPropertyTypes ve noUncheckedIndexedAccess gibi additional compiler flag'lerini de içeriyor. Bu flag'ler optional property'lerde undefined assignment'ı engelliyor ve array index erişimlerinde runtime güvenliği sağlıyor.
{
"compilerOptions": {
"strict": true,
"exactOptionalPropertyTypes": true,
"noUncheckedIndexedAccess": true,
"moduleResolution": "bundler",
"jsx": "react-jsx",
"types": ["react-native/types/strict"]
},
"extends": "@react-native/typescript-config/tsconfig.json"
}exactOptionalPropertyTypes flag'i, optional property'lere açıkça undefined atamasını yasaklar. Örneğin interface User { name?: string } varsa, user.name = undefined compile error verir. Bu, optional property ile undefined arasındaki semantic farkı korur. noUncheckedIndexedAccess ise array veya object index erişimlerini T | undefined olarak döner, böylece array[0] kullanımı optional chaining ya da null check gerektirir.
moduleResolution: "bundler" ayarı, Metro bundler'ın modern module resolution stratejisini yansıtır. react-native/types/strict type definition'ları, React Native core API'lerinde strict typing sağlar. Bu konfigürasyon sayesinde, Dimensions.get('window').width gibi yaygın API'ler bile compile-time'da type-checked olur.
React Navigation 7 ile Tip Güvenli Navigasyon
React Navigation 7, parametre tiplendirmesinde major improvement getirdi. Artık her route için parametre shape'i merkezi bir type definition'da tanımlanıyor ve navigation hooks bu tipleri otomatik olarak kullanıyor. Bu sayede, bir ekrana navigate ederken yanlış parametre göndermek compile error veriyor.
export type RootStackParamList = {
Home: undefined;
Profile: { userId: string };
Settings: undefined;
ArticleDetail: { articleId: string; source: 'feed' | 'search' };
};
export type AppTabParamList = {
Dashboard: undefined;
Explore: { category?: string };
Notifications: undefined;
};Bu type definition'lar, navigator oluştururken ve screen component'lerinde kullanılıyor. Screen component'leri NativeStackScreenProps gibi utility type'larla typed props alıyor.
import type { NativeStackScreenProps } from '@react-navigation/native-stack';
import type { RootStackParamList } from '../navigation/types';
type Props = NativeStackScreenProps<RootStackParamList, 'ArticleDetail'>;
export function ArticleDetailScreen({ route, navigation }: Props) {
// route.params.articleId is string — guaranteed by the type
// route.params.source is 'feed' | 'search' — no runtime check needed
const { articleId, source } = route.params;
// navigation.navigate('Profile', { userId: '123' }) — type-checked
// navigation.navigate('Profile', {}) — compile error: missing userId
return (
<ArticleView id={articleId} referrer={source} />
);
}Bu pattern, iki kritik sorunu çözüyor. Birincisi, route.params artık any değil, exact shape'e sahip. Yani articleId string olarak garanti ediliyor ve runtime check'e gerek kalmıyor. İkincisi, navigation.navigate() çağrıları type-checked. Eğer Profile ekranına userId göndermezseniz, IDE hemen hata gösterir.
useNavigation Hook Typing: Eğer component'inizde navigation prop'u yoksa, useNavigation<NativeStackNavigationProp<RootStackParamList>>() ile typed hook kullanabilirsiniz. Bu sayede functional component'ler de tam tip güvenliğine sahip olur.
TurboModule Codegen ile Tip Güvenli Native Bridge
New Architecture'ın en büyük kazanımlarından biri Codegen sistemi. Artık native module interface'lerini TypeScript'te tanımlıyorsunuz ve Codegen otomatik olarak iOS (C++/Objective-C++) ve Android (Java/Kotlin) binding'lerini generate ediyor. Bu sayede native taraf ile JS tarafı arasında type mismatch olamaz.
import type { TurboModule } from 'react-native';
import { TurboModuleRegistry } from 'react-native';
export interface Spec extends TurboModule {
getDeviceModel(): string;
getBatteryLevel(): Promise<number>;
getStorageInfo(): Promise<{
totalBytes: number;
freeBytes: number;
usedPercentage: number;
}>;
onBatteryChange(callback: (level: number) => void): void;
}
export default TurboModuleRegistry.getEnforcing<Spec>('DeviceInfo');Bu spec file'ı build sırasında native code generate eder. Android tarafında Kotlin implementation'ı şöyle görünür:
class DeviceInfoModule(reactContext: ReactApplicationContext) :
NativeDeviceInfoSpec(reactContext) {
// Return type enforced by generated NativeDeviceInfoSpec
override fun getDeviceModel(): String {
return Build.MODEL
}
override fun getBatteryLevel(): Promise<Double> {
val bm = reactContext.getSystemService(Context.BATTERY_SERVICE)
as BatteryManager
val level = bm.getIntProperty(
BatteryManager.BATTERY_PROPERTY_CAPACITY
).toDouble()
return Promise.resolve(level)
}
}NativeDeviceInfoSpec sınıfı Codegen tarafından otomatik generate edilir ve return type'lar TypeScript spec'teki tiplerle match etmek zorunda. Eğer getDeviceModel() fonksiyonu Int dönerse, compile error alırsınız. Bu pattern, eski NativeModules.DeviceInfo.getDeviceModel() gibi runtime-based API'lerin yerini alıyor ve type safety sağlıyor.
Codegen aynı zamanda iOS için C++ header'ları da generate eder. Bu sayede Swift/Objective-C++ implementation'ları da type-safe hale gelir. Cross-platform native module geliştirmede bu, game-changer bir özellik.
React Native mülakatlarında başarılı olmaya hazır mısın?
İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.
Generic Data Fetching ile Typed API Hook'ları
API çağrıları mobile app'lerin can damarı. TanStack Query (React Query) gibi library'lerle kombine edildiğinde, TypeScript generic'leri çok güçlü abstraction'lar sağlıyor. Custom hook'lar yazarken generic type parameter'ları kullanarak, API response shape'ini type-safe hale getirebilirsiniz.
import { useQuery, UseQueryOptions } from '@tanstack/react-query';
interface ApiResponse<T> {
data: T;
meta: { page: number; totalPages: number };
}
export function useApiQuery<T>(
key: readonly string[],
endpoint: string,
options?: Omit<UseQueryOptions<ApiResponse<T>>, 'queryKey' | 'queryFn'>
) {
return useQuery<ApiResponse<T>>({
queryKey: key,
queryFn: async () => {
const response = await fetch(`${API_BASE}${endpoint}`);
if (!response.ok) throw new ApiError(response.status);
return response.json() as Promise<ApiResponse<T>>;
},
...options,
});
}
// Usage — T is inferred as Article[]
interface Article {
id: string;
title: string;
publishedAt: string;
}
const { data, isLoading } = useApiQuery<Article[]>(
['articles', 'latest'],
'/articles?sort=latest'
);
// data.data is Article[] — fully typed
// data.meta.totalPages is numberBu pattern'in gücü generic inference'ta. useApiQuery<Article[]> çağrısı yaptığınızda, TypeScript otomatik olarak data.data tipini Article[] | undefined olarak belirler. IDE'nizde autocomplete çalışır ve data.data[0].title gibi erişimler type-safe hale gelir.
Omit<UseQueryOptions<ApiResponse<T>>, 'queryKey' | 'queryFn'> kısmı, TanStack Query'nin kendi option'larını (örneğin staleTime, retry) desteklerken, queryKey ve queryFn'i hook içinde override eder. Bu sayede consumer'lar sadece business logic ile ilgili option'ları geçer.
Bu hook pattern'ini mutation'lar için de kullanabilirsiniz. useApiMutation<CreateUserPayload, User> gibi bir hook, request body ve response type'ını type-safe hale getirir.
Discriminated Union'lar ile State Machine Modeling
Asenkron veri fetch eden screen'lerde state management karmaşık hale gelebilir: loading, error, empty, loaded gibi durumlar var. Bu durumları boolean flag'lerle yönetmek (isLoading, isError) type-safe değil çünkü invalid state kombinasyonları oluşabilir. Discriminated union'lar bu problemi elegant şekilde çözer.
type ScreenState<T> =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'error'; error: string; retryCount: number }
| { status: 'empty'; message: string }
| { status: 'loaded'; data: T; refreshedAt: Date };
// components/DataScreen.tsx
function renderContent<T>(state: ScreenState<T>, renderItem: (data: T) => ReactNode) {
switch (state.status) {
case 'idle':
return null;
case 'loading':
return <LoadingSpinner />;
case 'error':
// state.error is string here — TypeScript narrows automatically
return <ErrorBanner message={state.error} retries={state.retryCount} />;
case 'empty':
return <EmptyState message={state.message} />;
case 'loaded':
// state.data is T — fully typed
return renderItem(state.data);
}
}Bu pattern'in avantajları çok. İlk olarak, her state branch'inde sadece ilgili field'lar mevcut. status: 'error' ise state.error garanti var, state.data yok. TypeScript bunu otomatik olarak narrow ediyor. İkincisi, switch-case exhaustiveness checking var. Eğer yeni bir status eklerseniz (örneğin refetching), switch-case eksik olduğu için compile error alırsınız.
Üçüncüsü, invalid state kombinasyonları imkansız hale geliyor. isLoading: true ve data: [] gibi bir durum olamaz çünkü loading state'inin data field'ı yok. Bu pattern, finite state machine prensiplerine dayanıyor ve production app'lerde bug sayısını ciddi oranda azaltıyor.
Partial State Object Anti-Pattern: setState({ isLoading: true }) gibi partial update'ler discriminated union'larla çalışmaz. State transition'larını explicit şekilde yapmanız gerekir: setState({ status: 'loading' }). Bu başta zahmetli görünse de, uzun vadede state bug'larını minimize eder.
React Native TypeScript Mülakat Soruları
Soru 1: Codegen sisteminin eski NativeModules API'sine göre avantajları nedir?
Codegen, TypeScript spec'ten otomatik olarak native binding'ler generate eder. Bu sayede JS-native arası type mismatch compile-time'da yakalanır. Eski NativeModules'ta NativeModules.MyModule.someMethod() runtime'da fail olabilirken, TurboModules build sırasında type error verir. Ayrıca Codegen, JSI üzerinden synchronous native call'lara izin verir, bu da performans iyileştirmesi sağlar. Eski Bridge mimarisinde tüm native call'lar asenkrondu ve JSON serialization overhead'i vardı.
Soru 2: noUncheckedIndexedAccess compiler flag'i ne işe yarar?
Bu flag, array ve object index erişimlerinde return type'ı T | undefined yapar. Örneğin const arr: string[] = ['a', 'b']; const item = arr[5]; kodu, flag olmadan item: string döner ama runtime'da undefined olabilir. Flag aktifken item: string | undefined döner ve optional chaining (arr[5]?.toUpperCase()) zorunlu hale gelir. Bu, out-of-bounds erişimlerden kaynaklanan runtime crash'leri önler.
Soru 3: React Navigation'da param type'ları nasıl enforce edilir?
ParamList type'ı (RootStackParamList) tanımlanır ve navigator ile screen component'lerinde kullanılır. Screen component'ler NativeStackScreenProps<ParamList, 'ScreenName'> generic type'ını alır. Bu sayede route.params exact shape'e sahip olur. navigation.navigate() çağrıları da type-checked olur; yanlış parametre gönderirseniz compile error alırsınız. useNavigation hook'u da useNavigation<NavigationProp<ParamList>>() ile typed kullanılabilir.
Soru 4: Discriminated union pattern'inde "exhaustiveness checking" nasıl çalışır?
TypeScript, switch-case statement'larında union'ın tüm variant'larını kontrol eder. Eğer bir variant handle edilmezse, switch sonunda default: const _exhaustiveCheck: never = state; gibi bir check ekleyebilirsiniz. Yeni bir variant eklendiğinde bu satır compile error verir çünkü state artık never type'ına assign edilemez. Modern TypeScript (5.0+) bunu otomatik olarak implicit return type checking ile yapar.
Soru 5: TurboModules'un lazy initialization mekanizması nedir?
TurboModules, ilk kullanımda initialize edilir (lazy loading). Eski NativeModules'ta tüm native modüller app start'ta eager load edilirdi, bu da startup time'ı artırırdı. TurboModuleRegistry.get() çağrısı yapıldığında module initialize olur. Bu sayede kullanılmayan modüller memory'de yer kaplamaz. Ayrıca JSI sayesinde native module instance'ları JavaScript heap'te değil native heap'te tutulur, bu da memory overhead'ini azaltır.
Soru 6: Generic hook'larda type inference nasıl optimize edilir?
Generic parameter'ları explicit geçmek yerine, mümkün olduğunca inference kullanın. Örneğin useApiQuery hook'unda endpoint string'inden response type'ı çıkarılamaz, bu yüzden <Article[]> explicit geçilir. Ancak useState gibi hook'larda initial value'dan inference yapılabilir: useState({ count: 0 }) otomatik olarak { count: number } type'ı verir. Generic constraint'ler (<T extends object>) de inference'ı kısıtlayarak yanlış tip kullanımını engeller.
Pratik yapmaya başla!
Mülakat simülatörleri ve teknik testlerle bilgini test et.
Sonuç: 2026'da React Native TypeScript Standartları
React Native ekosisteminde TypeScript artık opsiyonel değil, zorunlu bir standart haline geldi. Modern projeler aşağıdaki pattern'leri benimsiyor:
- Strict compiler flag'leri:
exactOptionalPropertyTypesvenoUncheckedIndexedAccessile runtime güvenlik - TurboModule Codegen: Native bridge'de compile-time type safety
- Typed navigation: React Navigation 7 ile parametre ve route type enforcement
- Generic API hook'ları: TanStack Query ile reusable, type-safe data fetching
- Discriminated union'lar: State machine modeling ile invalid state'lerin önlenmesi
- JSI-based architecture: Synchronous native call'lar ve performans optimizasyonu
Bu pattern'leri benimseyen ekipler, production'da runtime error oranını %60-70 oranında düşürdü. TypeScript'in compile-time guarantees'i, mobil app geliştirmede test yükünü azaltıyor ve refactoring confidence'ını artırıyor. 2026'da React Native ile production app geliştiriyorsanız, bu mimari pattern'leri kullanmak artık best practice değil, standard gereksinim.
Pratik yapmaya başla!
Mülakat simülatörleri ve teknik testlerle bilgini test et.
Etiketler
Paylaş
İlgili makaleler

2026'da React Native Yeni Mimari: Hermes V1, Bridgeless Mod ve Mülakat Soruları
React Native Yeni Mimari 2026'da Hermes V1, Bridgeless Mod, TurboModules ve Fabric ile varsayılan olarak gelir. Performans kazanımları, geçiş kalıpları ve temel mülakat soruları hakkında kapsamlı inceleme.

2026'da React Native 0.85: Yeni Animasyon Backend'i, Katı TypeScript API ve Mülakat Soruları
React Native 0.85, Shared Animation Backend, post-bridge mimari ve Metro TLS desteği sunuyor. Kod örnekleri ve mülakat sorularıyla derinlemesine inceleme.

React Native'de Expo Router: Dosya Tabanlı Navigasyon Rehberi
React Native'de Expo Router ile dosya tabanlı navigasyon rehberi — dinamik rotalar, sekme navigasyonu, modal ekranlar ve rota koruması. 2026 güncel kaynak.