# React Native dan TypeScript 2026: Arsitektur Type-Safe, Codegen, serta Pertanyaan Wawancara Teknis > Pelajari arsitektur type-safe React Native dengan TypeScript di 2026: konfigurasi Strict API, typed navigation, TurboModules via Codegen, discriminated unions, dan pertanyaan wawancara mobile developer. - Published: 2026-06-16 - Updated: 2026-06-16 - Author: SharpSkill - Tags: react-native, typescript, mobile-development, turbomodules, interview - Reading time: 8 min --- Ekosistem React Native mengalami transformasi fundamental sepanjang paruh pertama 2026. Versi 0.86 yang dirilis Juni 2026 membawa React 19.1, arsitektur bridgeless secara default, dan Strict TypeScript API yang menjadikan TypeScript bukan sekadar pelengkap melainkan fondasi kontrak antara lapisan JavaScript dan native. Codegen kini membaca spesifikasi TypeScript untuk menghasilkan interface C++, Objective-C++, dan Kotlin secara otomatis, sehingga ketidaksesuaian tipe terdeteksi saat kompilasi, bukan saat aplikasi sudah berjalan di perangkat pengguna. Artikel ini mengupas pola arsitektur type-safe yang relevan untuk produksi, dilengkapi contoh kode dan pertanyaan wawancara teknis yang kerap diajukan pada tahun 2026. > **Perubahan penting di 2026** > > React Native 0.80 memperkenalkan Strict TypeScript API secara opt-in, versi 0.82 menghapus legacy bridge secara permanen, dan versi 0.85 menghilangkan interop layer terakhir. Per versi 0.86 (Juni 2026), setiap proyek baru dimulai dengan arsitektur bridgeless penuh dan TypeScript types yang di-generate langsung dari source code. ## Mengapa TypeScript Menjadi Pilihan Default untuk React Native Sejak React Native 0.76, perintah `npx react-native init` secara otomatis menghasilkan scaffolding proyek TypeScript. Perubahan tersebut bukan semata soal preferensi developer, melainkan kebutuhan arsitektural. Pada era legacy bridge, komunikasi antara JavaScript dan kode native bergantung pada serialisasi JSON dan parsing manual melalui `ReadableMap` di Android serta `NSDictionary` di iOS. Kontrak berbasis string semacam ini rentan gagal secara diam-diam saat runtime. Hadirnya Codegen mengubah paradigma tersebut secara mendasar. Codegen membaca file spesifikasi TypeScript dan menghasilkan interface native yang mengikat secara ketat. Apabila sebuah method dideklarasikan mengembalikan `number` dalam spec TypeScript, interface native yang dihasilkan memaksa implementasi platform mengembalikan tipe numerik yang sesuai. Ketidakcocokan tipe langsung menyebabkan kegagalan kompilasi. [Dokumentasi resmi React Native](https://reactnative.dev/docs/typescript) mencakup konfigurasi dasar TypeScript. Namun pola-pola yang dibutuhkan dalam aplikasi produksi melangkah lebih jauh: typed navigation stacks, generic API hooks dengan TanStack Query, discriminated unions untuk manajemen state, serta TurboModule specs yang digerakkan Codegen. ## Mengonfigurasi Strict TypeScript API Strict TypeScript API yang diperkenalkan pada React Native 0.80 membatasi surface area API publik hanya pada types yang dihasilkan langsung dari source code framework. Fitur ini mencegah developer secara tidak sengaja bergantung pada modul internal yang dapat berubah sewaktu-waktu antar rilis minor. ```json // tsconfig.json { "compilerOptions": { "strict": true, "exactOptionalPropertyTypes": true, "noUncheckedIndexedAccess": true, "moduleResolution": "bundler", "jsx": "react-jsx", "types": ["react-native/types/strict"] }, "extends": "@react-native/typescript-config/tsconfig.json" } ``` Setelah konfigurasi di atas diterapkan, setiap upaya mengimpor dari subpath internal seperti `react-native/Libraries/Text/Text` akan menghasilkan type error. Seluruh import wajib berasal dari root package `react-native`, selaras dengan kebijakan deep-import deprecation yang berlaku sejak versi 0.80. Beberapa opsi compiler yang perlu diperhatikan secara khusus: `exactOptionalPropertyTypes` melarang assignment `undefined` secara eksplisit pada properti opsional kecuali tipe tersebut memang menyertakan `undefined` dalam union-nya. Sementara itu, `noUncheckedIndexedAccess` secara otomatis menambahkan `undefined` pada setiap operasi akses melalui indeks, sehingga developer dipaksa melakukan null check sebelum menggunakan nilai yang diakses via bracket notation. ## Type-Safe Navigation dengan React Navigation 7 [React Navigation 7.x](https://reactnavigation.org/docs/typescript/) menawarkan dukungan TypeScript yang matang. Inti dari pendekatan ini adalah mendefinisikan tipe `ParamList` yang memetakan setiap nama screen ke parameter yang diekspektasi, kemudian meneruskan tipe tersebut ke seluruh navigator dan screen component. ```typescript // navigation/types.ts 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; }; ``` Pada definisi di atas, setiap key mewakili nama screen dan value-nya mewakili parameter yang wajib disertakan saat navigasi. Screen `Home` serta `Settings` tidak memerlukan parameter (`undefined`). Screen `Profile` mewajibkan `userId` bertipe `string`, sedangkan `ArticleDetail` memerlukan `articleId` beserta `source` yang dibatasi pada literal union `'feed' | 'search'`. Komponen screen kemudian menerima props yang sudah ter-type secara otomatis tanpa perlu melakukan casting manual: ```typescript // screens/ArticleDetailScreen.tsx import type { NativeStackScreenProps } from '@react-navigation/native-stack'; import type { RootStackParamList } from '../navigation/types'; type Props = NativeStackScreenProps; 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 ( ); } ``` Manfaat utama dari pendekatan ini adalah menghilangkan satu kategori besar error runtime. Kesalahan navigasi ke screen dengan parameter yang tidak sesuai atau tidak lengkap akan terdeteksi pada saat build, jauh sebelum kode tersebut dijalankan di perangkat pengguna akhir. > **Mengetik useNavigation hook** > > Untuk komponen yang bukan children langsung dari screen, gunakan `useNavigation>()` untuk mendapatkan type safety yang sama tanpa perlu melakukan prop drilling. ## Membangun TurboModule Type-Safe dengan Codegen TurboModules hadir sebagai pengganti sistem Native Modules lama yang berkomunikasi melalui async bridge. Dalam arsitektur baru, file spesifikasi TypeScript berperan sebagai single source of truth. Codegen membaca file tersebut dan menghasilkan abstract class native yang wajib diimplementasikan oleh kode platform. Apabila spesifikasi dan implementasi tidak sinkron, proses build akan gagal. ```typescript // specs/NativeDeviceInfo.ts import type { TurboModule } from 'react-native'; import { TurboModuleRegistry } from 'react-native'; export interface Spec extends TurboModule { getDeviceModel(): string; getBatteryLevel(): Promise; getStorageInfo(): Promise<{ totalBytes: number; freeBytes: number; usedPercentage: number; }>; onBatteryChange(callback: (level: number) => void): void; } export default TurboModuleRegistry.getEnforcing('DeviceInfo'); ``` Spesifikasi di atas mendeskripsikan kontrak yang eksplisit: `getDeviceModel()` mengembalikan `string` secara sinkron, `getBatteryLevel()` mengembalikan `Promise` secara asinkron, dan `getStorageInfo()` mengembalikan Promise berisi objek dengan tiga field numerik. Menjalankan `npx react-native codegen` akan menghasilkan interface C++, Objective-C++, dan Java yang harus dipatuhi oleh implementasi native di setiap platform. Berikut contoh implementasi di sisi Android menggunakan Kotlin: ```kotlin // android/app/src/main/java/com/app/DeviceInfoModule.kt class DeviceInfoModule(reactContext: ReactApplicationContext) : NativeDeviceInfoSpec(reactContext) { // Return type enforced by generated NativeDeviceInfoSpec override fun getDeviceModel(): String { return Build.MODEL } override fun getBatteryLevel(): Promise { val bm = reactContext.getSystemService(Context.BATTERY_SERVICE) as BatteryManager val level = bm.getIntProperty( BatteryManager.BATTERY_PROPERTY_CAPACITY ).toDouble() return Promise.resolve(level) } } ``` Class `NativeDeviceInfoSpec` dihasilkan oleh Codegen berdasarkan spesifikasi TypeScript. Compiler Kotlin akan menolak kode yang tidak memenuhi kontrak tersebut. Sebagai contoh, mengembalikan `Int` alih-alih `Double` untuk `getBatteryLevel()` akan langsung menghasilkan compile error. Pendekatan ini secara efektif menghilangkan bug silent type coercion yang umum terjadi pada era parsing `ReadableMap` dan `NSDictionary`. ## Generic Data Fetching dengan Typed API Hooks Aplikasi React Native pada umumnya memiliki banyak screen yang melakukan fetch data dari REST API. Tanpa abstraksi yang tepat, logika fetch akan terduplikasi di setiap screen. Pola typed hook generik berikut mengatasi permasalahan tersebut sambil mempertahankan type inference secara penuh: ```typescript // hooks/useApiQuery.ts import { useQuery, UseQueryOptions } from '@tanstack/react-query'; interface ApiResponse { data: T; meta: { page: number; totalPages: number }; } export function useApiQuery( key: readonly string[], endpoint: string, options?: Omit>, 'queryKey' | 'queryFn'> ) { return useQuery>({ queryKey: key, queryFn: async () => { const response = await fetch(`${API_BASE}${endpoint}`); if (!response.ok) throw new ApiError(response.status); return response.json() as Promise>; }, ...options, }); } // Usage — T is inferred as Article[] interface Article { id: string; title: string; publishedAt: string; } const { data, isLoading } = useApiQuery( ['articles', 'latest'], '/articles?sort=latest' ); // data.data is Article[] — fully typed // data.meta.totalPages is number ``` Parameter generik `T` mengalir dari titik pemanggilan hook hingga ke komponen yang mengonsumsi hasilnya. Ketika developer memanggil `useApiQuery(...)`, TypeScript secara otomatis menyimpulkan bahwa `data.data` bertipe `Article[]` dan `data.meta.totalPages` bertipe `number`. Tidak diperlukan `as` cast maupun `any` type di mana pun dalam chain tersebut. Penggunaan `Omit` untuk mengecualikan `queryKey` dan `queryFn` dari parameter opsi mencegah consumer hook menimpa logika inti secara tidak disengaja. Di sisi lain, konfigurasi seperti `staleTime`, `enabled`, dan `refetchInterval` tetap dapat dikustomisasi sesuai kebutuhan masing-masing screen. ## Discriminated Unions untuk State Machines Mengelola state layar yang kompleks dengan boolean flags seperti `isLoading`, `isError`, dan `hasData` merupakan pendekatan yang rawan masalah. Kombinasi flags tersebut dapat menghasilkan state yang secara logika mustahil. Discriminated unions menawarkan solusi yang lebih aman di level type system: ```typescript // types/screen-state.ts type ScreenState = | { 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(state: ScreenState, renderItem: (data: T) => ReactNode) { switch (state.status) { case 'idle': return null; case 'loading': return ; case 'error': // state.error is string here — TypeScript narrows automatically return ; case 'empty': return ; case 'loaded': // state.data is T — fully typed return renderItem(state.data); } } ``` Setiap branch dalam union merepresentasikan satu state yang eksklusif. State `loading` tidak mungkin membawa properti `data`, dan state `error` selalu memiliki informasi `retryCount` untuk keperluan debugging. TypeScript melakukan type narrowing secara otomatis di dalam setiap case, sehingga akses terhadap properti yang tidak relevan dengan state tersebut akan menghasilkan compile error. > **Hindari pola partial state objects** > > Anti-pattern yang umum dijumpai: `{ isLoading: boolean; error?: string; data?: T }`. Pola ini memungkinkan kombinasi state seperti `{ isLoading: true, error: 'fail', data: [...] }` yang mengandung tiga sinyal kontradiktif secara bersamaan. Discriminated unions mencegah kemungkinan tersebut di level type system. ## Pertanyaan Wawancara React Native TypeScript Pertanyaan-pertanyaan berikut merepresentasikan topik yang kerap diuji oleh tim engineering senior pada wawancara mobile developer di tahun 2026, seiring New Architecture dan TypeScript telah menjadi standar industri. **Bagaimana mekanisme Codegen dalam menegakkan type safety di batas JavaScript-native?** Codegen membaca file spesifikasi TypeScript (atau Flow) lalu menghasilkan kode interface untuk C++, Objective-C++, dan Java/Kotlin. Interface native yang dihasilkan memaksakan kecocokan persis pada method signatures, parameter types, dan return types sebagaimana didefinisikan dalam spec. Apabila implementasi native menyimpang dari kontrak tersebut, misalnya mengembalikan `Int` padahal spec mendeklarasikan `Double` atau menghilangkan field dari sebuah struct, compiler native akan menolak build. Mekanisme ini menggeser deteksi error tipe dari runtime crashes menjadi build-time failures. **Apa yang dimaksud dengan Strict TypeScript API dan apa signifikansinya?** Diperkenalkan pada React Native 0.80, Strict TypeScript API menghasilkan type definitions langsung dari source code React Native, menggantikan pendekatan lama yang mengandalkan file `.d.ts` buatan tangan. API ini membatasi seluruh import ke root package `react-native` dan mendepresiasi deep imports. Implikasi utamanya: refactoring internal framework tidak akan merusak kode consumer selama consumer hanya menggunakan strict types. Pengaktifannya dilakukan melalui opsi `"types": ["react-native/types/strict"]` di dalam `tsconfig.json`. **Bagaimana cara menerapkan typing pada React Navigation params di nested navigators?** Setiap navigator memerlukan tipe `ParamList` tersendiri, kemudian digabungkan menggunakan `NavigatorScreenParams`. Untuk skenario tab navigator yang bersarang di dalam stack navigator, param list stack harus mereferensikan tipe tab: `type RootStack = { Main: NavigatorScreenParams; Modal: { id: string } }`. Setiap pemanggilan `navigate()` akan diperiksa tipe-nya menelusuri seluruh hierarki nesting, sehingga nama screen yang keliru atau parameter yang kurang langsung terdeteksi pada compile time. **Permasalahan apa yang diselesaikan oleh discriminated unions dalam state management React Native?** Discriminated unions memodelkan state yang bersifat mutually exclusive (loading, error, loaded) sebagai branch-branch terpisah dari sebuah union type, dengan field `status` sebagai diskriminator. TypeScript melakukan narrowing tipe di setiap branch switch statement, sehingga akses terhadap `state.data` hanya dimungkinkan ketika `state.status === 'loaded'`. Pendekatan ini mencegah state yang mustahil, seperti loading indicator yang tampil bersamaan dengan data error, yang merupakan kategori bug yang tidak dapat dicegah oleh kombinasi optional fields dan boolean flags. **Jelaskan perbedaan mendasar antara TurboModules dan sistem Native Modules lama.** Native Modules lama berkomunikasi melalui async bridge dengan men-serialize seluruh data ke format JSON. TurboModules menggunakan JSI (JavaScript Interface) untuk melakukan pemanggilan C++ secara langsung dan sinkron tanpa overhead serialisasi. TurboModules juga memuat secara lazy, yaitu hanya ketika pertama kali digunakan, bukan saat startup aplikasi, sehingga mengurangi cold start time secara signifikan. Dari perspektif type safety, TurboModules menggunakan Codegen untuk menghasilkan type-safe interfaces dari TypeScript specs, sedangkan sistem lama mengandalkan parsing `ReadableMap` / `NSDictionary` yang rentan terhadap runtime type coercion. Untuk [pertanyaan wawancara React Native](/technologies/react-native/interview-questions/rn-native-modules) lainnya, tersedia pembahasan mendalam mengenai JSI, Fabric, dan arsitektur bridgeless. ## Kesimpulan Berikut rangkuman pola arsitektur type-safe React Native TypeScript yang perlu dikuasai di tahun 2026: - **Strict TypeScript API (0.80+)** membatasi import ke surface area API publik yang stabil, sehingga perubahan internal framework tidak berdampak pada kode consumer. Fitur ini sebaiknya diaktifkan di setiap proyek baru - **Codegen** menghasilkan native interfaces dari file spesifikasi TypeScript, menggeser deteksi error tipe dari runtime crashes ke build-time failures di batas JavaScript-native - **Typed navigation params** melalui `RootStackParamList` dan `NativeStackScreenProps` menangkap kesalahan nama screen serta parameter yang tidak lengkap sebelum aplikasi dijalankan - **Discriminated unions** memodelkan state screen sebagai branch yang mutually exclusive, membuat kombinasi state yang mustahil tidak dapat direpresentasikan di level type system - **TurboModules** dengan typed specs menggantikan parsing `ReadableMap` dan `NSDictionary`, menegakkan type safety penuh dari JavaScript melalui C++ hingga kode platform native - **Generic API hooks** dengan [TanStack Query](https://tanstack.com/query/latest) mempertahankan type inference dari endpoint hingga komponen UI tanpa memerlukan cast manual --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/id/blog/react-native/react-native-typescript-type-safe-architecture