React Native ve TypeScript 2026: Tip-Güvenli Mimari ve Mülakat Soruları

TypeScript, Codegen, TurboModule ve Strict TypeScript API ile tip-güvenli React Native uygulamaları oluşturma. Mimari pattern'ler, typed navigasyon, 0.87 toolchain gereksinimleri ve mülakat sorularını kapsıyor.

React Native TypeScript tip güvenli mimari ve kod örnekleri

React Native TypeScript tip güvenliği 2026 ortasına kadar önemli ölçüde olgunlaştı ve 0.87 sürümü Strict TypeScript API'yi varsayılan hale getirerek büyük bir toolchain modernizasyonunu tamamladı. TypeScript artık JavaScript ile native kod arasında opsiyonel bir yapıştırıcı değil: component props'larından TurboModule interface'lerine kadar tüm kontratı yönetiyor ve uyumsuzlukları production crash logları yerine build zamanında yakalıyor.

0.87'de değişenler

React Native 0.87 (Ağustos 2026) Strict TypeScript API'yi zorunlu varsayılan haline getiriyor. Ayrıca minimum gereksinimleri Node.js 22.13+, Kotlin 2.0+ ve Android Gradle Plugin 9 olarak yükseltiyor. Legacy deep imports için opt-out sadece 0.88'e kadar mevcut.

TypeScript Neden React Native Projelerinin Varsayılanı Oldu

0.76 sürümünden bu yana her npx react-native init çağrısı bir TypeScript projesi oluşturuyor. Ancak asıl değişim native sınırda gerçekleşti. Codegen'den önce, geliştiriciler JavaScript'ten Objective-C veya Kotlin'e geçerken manuel tip assertion'lar yazıyordu; bu, runtime'da sessizce bozulan string-typed bir kontrattı. Codegen, TypeScript spec dosyalarını okuyup otomatik olarak C++, Objective-C++ ve Java/Kotlin interface'lerini üretiyor. TypeScript spec'i number döndüren bir metot tanımlıyorsa, üretilen native interface bu kısıtlamayı compile time'da zorluyor.

React Native dokümantasyonu temel kurulumu kapsıyor, ancak production'da önemli olan tip-güvenli pattern'ler daha ileri gidiyor: typed navigation stack'leri, generic API hook'ları, state machine'ler için discriminated union'lar ve Codegen-driven TurboModule spec'leri.

Strict TypeScript API: Opt-In'den Varsayılana

Strict TypeScript API, React Native 0.80'de opt-in bir özellik olarak tanıtıldı. 0.87 itibarıyla tüm yeni projeler için zorunlu varsayılan. Tipler, manuel olarak bakılmak yerine doğrudan React Native'in kaynak kodundan üretiliyor ve dokümante edilen API ile gerçek implementasyon arasındaki sapma ortadan kaldırılıyor.

tsconfig.json (0.87+ varsayılan konfigürasyonu)json
{
  "extends": "@react-native/typescript-config",
  "compilerOptions": {
    "strict": true,
    "exactOptionalPropertyTypes": true,
    "noUncheckedIndexedAccess": true
  }
}

Bu konfigürasyonla, react-native/Libraries/Text/Text gibi bir alt yoldan herhangi bir şey import etmek tip hatası tetikliyor. Tüm import'lar kök react-native paketinden gelmeli. Eğer bir library veya eski codebase hâlâ deep import'lara dayanıyorsa, 0.88'e kadar geçici bir opt-out mevcut:

json
{
  "extends": "@react-native/typescript-config",
  "compilerOptions": {
    "customConditions": ["react-native", "react-native-legacy-deep-imports"]
  }
}

Bu opt-out 0.89'da kaldırılacak. Migrasyon bundan önce yapılmalı.

0.87'de Toolchain Gereksinimleri

React Native 0.87, build chain boyunca minimum sürümleri yükseltiyor:

BileşenMinimum
Node.js22.13.0
Kotlin2.0 (dahil edilen: 2.2.0)
Android Gradle Plugin9.x
Android compileSdk34 (min), 37 (target)

Android için AGP 9 ek konfigürasyon gerektiriyor:

properties
# android/gradle.properties
android.builtInKotlin=false
android.newDsl=false

Bu gereksinimler 0.87+ hedefleyen tüm projeler için geçerli. New Architecture migrasyon rehberi bu değişikliklerin daha geniş bağlamını kapsıyor.

React Navigation 7 ile Tip-Güvenli Navigasyon

React Navigation 7.x birinci sınıf TypeScript desteği sağlıyor. Ana pattern: her ekran adını beklenen parametrelerine eşleyen bir RootStackParamList tipi tanımlamak ve bu tipi navigator'lar ile screen component'leri boyunca geçirmek.

navigation/types.tstypescript
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;
};

Screen component'leri manuel cast olmadan typed props alıyor:

screens/ArticleDetailScreen.tsxtypescript
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' }) is type-checked
  // navigation.navigate('Profile', {}) causes a compile error: missing userId
  return (
    <ArticleView id={articleId} referrer={source} />
  );
}

Bu, bir bütün runtime hata sınıfını ortadan kaldırıyor: yanlış veya eksik parametrelerle bir ekrana navigate etmek build time'da başarısız oluyor.

useNavigation hook tiplendirmesi

Doğrudan screen child'ı olmayan component'ler için, prop drilling olmadan aynı tip güvenliğini elde etmek için useNavigation<NativeStackNavigationProp<RootStackParamList>>() kullanılmalı.

Codegen ile Tip-Güvenli TurboModule Oluşturma

TurboModule'ler eski Native Modules sisteminin yerini alıyor. TypeScript spec dosyası tek doğru kaynak olarak işlev görüyor ve Codegen ondan native interface'leri üretiyor. Spec ile native implementasyon farklılaşırsa build başarısız oluyor.

specs/NativeDeviceInfo.tstypescript
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');

npx react-native codegen çalıştırmak ilgili C++, Objective-C++ ve Java interface'lerini üretiyor. Native implementasyon her metot imzasıyla tam olarak eşleşmeli. Örneğin, getStorageInfo üç numerik alana sahip bir obje döndürmeli; farklı bir şekil döndürmek native tarafta compile-time hatası veriyor.

android/app/src/main/java/com/app/DeviceInfoModule.ktkotlin
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)
    }
}

Bu yaklaşım, eski mimaride sessiz tip zorlama hatalarına neden olan ReadableMap ve NSDictionary parsing'ini ortadan kaldırıyor. Native module sistemi hakkında daha derin bir bakış için native modules mülakat soruları sayfasına bakılabilir.

React Native mülakatlarında başarılı olmaya hazır mısın?

İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.

Typed API Hook'larıyla Generic Veri Çekme

Tekrar kullanılabilir typed hook pattern'i, tam tip inference'ı korurken ekranlar arasında fetch mantığı tekrarını önlüyor:

hooks/useApiQuery.tstypescript
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 number

Generic parametre T tüm zincir boyunca akıyor: hook çağrı noktasından, query function üzerinden, sonucu tüketen component'e kadar. as cast'leri yok, any tipleri yok.

State Machine'ler için Discriminated Union'lar

Karmaşık ekran state'leri (loading, error, empty, loaded) en iyi şekilde optional field'lar yığını yerine discriminated union'lar olarak modellenir:

types/screen-state.tstypescript
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 imkânsız state'leri temsil edilemez kılıyor. Bir loading state'i yanlışlıkla eski data taşıyamaz ve bir error state'i her zaman debugging için bağlam içerir.

Kısmi state objeleri kullanmaktan kaçınma

Yaygın bir anti-pattern: { isLoading: boolean; error?: string; data?: T }. Bu, { isLoading: true, error: 'fail', data: [...] } gibi state'lere izin veriyor, aynı anda üç çelişkili sinyal. Discriminated union'lar bunu tip seviyesinde engelliyor.

React Native TypeScript Mülakat Soruları

Bu sorular, New Architecture ve TypeScript'in standart olduğu 2026 mülakatlarda senior mobile engineering ekiplerinin sorduğu soruları yansıtıyor.

Codegen, JavaScript-native sınırında tip güvenliğini nasıl zorluyor?

Codegen, TypeScript (veya Flow) spec dosyalarını okuyor ve C++, Objective-C++ ve Java/Kotlin interface kodu üretiyor. Üretilen native interface'ler spec'te tanımlanan tam metot imzalarını, parametre tiplerini ve dönüş tiplerini zorluyor. Native implementasyon sapma gösterirse (spec Double tanımlarken Int döndürme veya bir struct'tan alan atlama) native compiler build'i reddediyor. Bu, tip hatalarını runtime crash'lerden build-time hatalarına taşıyor.

Strict TypeScript API nedir ve neden önemli?

Strict TypeScript API, elle yazılmış .d.ts dosyaları bakımı yerine doğrudan React Native'in kaynak kodundan tipler üretiyor. 0.87'de zorunlu varsayılan oldu. Import'ları kök react-native paketine kısıtlıyor ve deep import'ları deprecate ediyor. Bu kararlı bir public API yüzeyi tanımlıyor: eğer consumer'lar sadece strict tipleri kullanırsa internal refactor'lar consumer kodunu bozamaz. customConditions aracılığıyla geçici opt-out 0.88'e kadar mevcut.

Nested navigator'lar arasında React Navigation parametreleri nasıl tiplendiriliyor?

Navigator başına bir ParamList tipi tanımlanır ve NavigatorScreenParams kullanılarak birleştirilir. Bir stack içinde nested bir tab navigator için, stack'in param list'i tab'inkine referans verir: type RootStack = { Main: NavigatorScreenParams<TabParamList>; Modal: { id: string } }. Her navigate() çağrısı tam nesting hiyerarşisi boyunca tip-kontrollü olur, yanlış ekran adlarını veya eksik parametreleri compile time'da yakalar.

Discriminated union'lar React Native state yönetiminde hangi sorunu çözüyor?

Discriminated union'lar karşılıklı dışlayıcı state'leri (loading, error, loaded) status alanıyla anahtarlanan union tipinin ayrı dalları olarak modelliyor. TypeScript, switch statement'ın her dalında tipi daraltıyor, böylece state.data'ya erişim sadece state.status === 'loaded' olduğunda mümkün. Bu, error data yanında loading indicator gösterme gibi imkânsız state'leri engelliyor; optional field'lar ve boolean flag'lerin engelleyemediği bir hata sınıfı.

TurboModule'ler ile eski Native Modules sistemi arasındaki farkı açıklayın.

Native Modules asenkron bridge üzerinden iletişim kuruyordu ve tüm verileri JSON'a serialize ediyordu. TurboModule'ler, serializasyon overhead'i olmadan senkron, doğrudan C++ çağrıları için JSI (JavaScript Interface) kullanıyor. Ayrıca lazy load oluyorlar (uygulama başlangıcı yerine ilk kullanımda, cold start süresini azaltarak) ve TypeScript spec'lerinden tip-güvenli interface'ler üretmek için Codegen kullanıyorlar. Eski sistem runtime tip zorlaması ile ReadableMap / NSDictionary parsing'ine dayanıyordu; TurboModule'ler tipleri compile time'da zorluyor.

React Native 0.87'de hangi API'ler kaldırıldı?

0.87, InteractionManager'ı (requestIdleCallback kullanılmalı), NativeMethods / NativeMethodsMixin tiplerini (HostInstance kullanılmalı) ve birkaç StatusBar prop'unu kaldırdı. src/private/ yollarına deep import'lar artık tip hataları. TurboModule'ler artık her zaman etkin olduğu için useTurboModules flag'i de kaldırıldı.

Daha fazla React Native mülakat sorusu için mimari, performans ve debugging konularını kapsayan tam rehbere bakılabilir.

Pratik yapmaya başla!

Mülakat simülatörleri ve teknik testlerle bilgini test et.

Kaynaklar

2026'da React Native TypeScript Hakkında Hatırlanması Gerekenler

  • Strict TypeScript API (0.87'de zorunlu) import'ları kararlı public yüzeye kısıtlıyor ve internal değişikliklerden kaynaklanan bozulmaları önlüyor. Legacy deep import'lar için opt-out sadece 0.88'e kadar mevcut
  • Codegen, TypeScript spec dosyalarından native interface'ler üretiyor ve tip hatalarını runtime crash'lerden JS-native sınırı boyunca build-time hatalarına taşıyor
  • 0.87'de toolchain minimumlari: Node.js 22.13+, Kotlin 2.0+, AGP 9, compileSdk 34+
  • RootStackParamList ve NativeStackScreenProps aracılığıyla typed navigasyon parametreleri, uygulama çalışmadan önce yanlış ekran adlarını ve eksik parametreleri yakalıyor
  • Discriminated union'lar ekran state'lerini karşılıklı dışlayıcı dallar olarak modelliyor ve imkânsız state'leri tip seviyesinde temsil edilemez kılıyor
  • Typed spec'li TurboModule'ler eski ReadableMap / NSDictionary parsing'inin yerini alıyor ve JavaScript'ten C++ üzerinden platform-native koda tam tip güvenliği zorluyor
  • TanStack Query ile generic API hook'ları, manuel cast olmadan endpoint'ten component'e tip inference'ı koruyor

Pratik yapmaya başla!

Mülakat simülatörleri ve teknik testlerle bilgini test et.

Günün meydan okuması

React Native kodundaki hatayı bulabilir misin?

Gerçek bir kod parçası, gizli bir hata, günde bir deneme. Denemek için hesap gerekmez.

Anthony Fillion-Maillet

Yazan:

Anthony Fillion-Maillet

SharpSkill kurucusu

10 yılı aşkın süredir fullstack geliştirici. SharpSkill’i yönetiyor ve burada yayımlanan her şeyden sorumlu.

25 Ağustos 2026 tarihinde güncellendi

Etiketler

#react-native
#typescript
#mobile-development
#new-architecture
#turbomodules

Paylaş

İlgili makaleler