React Native en TypeScript in 2026: type-veilige architectuur en sollicitatievragen

Bouw type-veilige React Native-apps met TypeScript, Codegen, TurboModules en de Strict TypeScript API. Architectuurpatronen, getypeerde navigatie en sollicitatievragen voor 2026.

Type-veilige React Native-architectuur met TypeScript, code en mobiele apparaten

De type-safety van React Native met TypeScript is medio 2026 flink volwassen geworden: versie 0.86 levert React 19.1, de Strict TypeScript API en een volledig bridgeless architectuur op basis van Codegen. TypeScript is niet langer optionele lijm tussen JavaScript en native code. Het stuurt het volledige contract aan, van component-props tot TurboModule-interfaces, en vangt afwijkingen al tijdens de build op in plaats van in crash-logs in productie.

Wat veranderde er in 2026

React Native 0.80 introduceerde de optionele Strict TypeScript API, 0.82 verwijderde de oude bridge definitief en 0.85 schrapte de laatste interop-laag. Sinds 0.86 (juni 2026) start elk nieuw project volledig bridgeless, met TypeScript-types die direct uit de broncode worden gegenereerd.

Waarom TypeScript nu de standaard is voor React Native-projecten

Elke aanroep van npx react-native init zet sinds versie 0.76 een TypeScript-project op. De echte verschuiving vond echter plaats op de native grens. Vóór Codegen schreven ontwikkelaars handmatige type-asserties bij de overgang van JavaScript naar Objective-C of Kotlin, een via strings gedefinieerd contract dat stilletjes brak tijdens runtime. Codegen leest TypeScript-specificatiebestanden en genereert daaruit automatisch C++-, Objective-C++- en Java/Kotlin-interfaces. Declareert de TypeScript-specificatie een methode die number teruggeeft, dan dwingt de gegenereerde native interface die beperking af tijdens compilatie.

De React Native-documentatie behandelt de basisopzet, maar de type-veilige patronen die er in productie toe doen, gaan verder: getypeerde navigatiestacks, generieke API-hooks, discriminated unions voor state machines en Codegen-gestuurde TurboModule-specificaties.

De Strict TypeScript API opzetten

De Strict TypeScript API, geïntroduceerd in React Native 0.80, beperkt het publieke API-oppervlak tot types die direct uit de broncode worden gegenereerd. Dat voorkomt onbedoelde afhankelijkheid van interne modules die tussen minor-versies kunnen breken.

tsconfig.jsonjson
{
  "compilerOptions": {
    "strict": true,
    "exactOptionalPropertyTypes": true,
    "noUncheckedIndexedAccess": true,
    "moduleResolution": "bundler",
    "jsx": "react-jsx",
    "types": ["react-native/types/strict"]
  },
  "extends": "@react-native/typescript-config/tsconfig.json"
}

Met deze configuratie levert het importeren van iets uit een subpad zoals react-native/Libraries/Text/Text een type-fout op. Alle imports moeten uit het root-pakket react-native komen, in lijn met de sinds 0.80 afgedwongen deprecatie van diepe imports.

Type-veilige navigatie met React Navigation 7

React Navigation 7.x biedt eersteklas TypeScript-ondersteuning. Het kernpatroon: definieer een type RootStackParamList dat elke schermnaam koppelt aan de verwachte params, en geef dat type vervolgens door aan navigators en schermcomponenten.

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;
};

Schermcomponenten ontvangen dan getypeerde props zonder handmatige cast:

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 — gegarandeerd door het type
  // route.params.source is 'feed' | 'search' — geen runtime-controle nodig
  const { articleId, source } = route.params;

  // navigation.navigate('Profile', { userId: '123' }) — typegecontroleerd
  // navigation.navigate('Profile', {}) — compilatiefout: userId ontbreekt
  return (
    <ArticleView id={articleId} referrer={source} />
  );
}

Dit elimineert een hele categorie runtime-fouten: navigeren naar een scherm met verkeerde of ontbrekende params faalt al tijdens de build.

De useNavigation-hook typen

Voor componenten die geen directe schermkinderen zijn, levert useNavigation<NativeStackNavigationProp<RootStackParamList>>() dezelfde type-veiligheid zonder prop drilling.

Een type-veilige TurboModule bouwen met Codegen

TurboModules vervangen het oude Native Modules-systeem. Het TypeScript-specificatiebestand dient als enige bron van waarheid, want Codegen genereert daaruit de native interfaces. Lopen specificatie en native implementatie uiteen, dan faalt de build.

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');

Het uitvoeren van npx react-native codegen genereert de bijbehorende C++-, Objective-C++- en Java-interfaces. De native implementatie moet elke methodesignatuur exact naleven. Zo moet getStorageInfo een object met drie numerieke velden teruggeven; een afwijkende vorm veroorzaakt een compilatiefout aan de native kant.

android/app/src/main/java/com/app/DeviceInfoModule.ktkotlin
class DeviceInfoModule(reactContext: ReactApplicationContext) :
    NativeDeviceInfoSpec(reactContext) {

    // Retourtype afgedwongen door gegenereerde 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)
    }
}

Deze aanpak elimineert het parsen van ReadableMap en NSDictionary dat in de oude architectuur stille bugs door type-coercie veroorzaakte.

Klaar om je React Native gesprekken te halen?

Oefen met onze interactieve simulatoren, flashcards en technische tests.

Generieke data-fetching met getypeerde API-hooks

Een herbruikbaar patroon voor getypeerde hooks voorkomt het dupliceren van fetch-logica over schermen heen, terwijl de volledige type-inferentie behouden blijft:

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,
  });
}

// Gebruik — T wordt afgeleid als Article[]
interface Article {
  id: string;
  title: string;
  publishedAt: string;
}

const { data, isLoading } = useApiQuery<Article[]>(
  ['articles', 'latest'],
  '/articles?sort=latest'
);
// data.data is Article[] — volledig getypeerd
// data.meta.totalPages is number

De generieke parameter T stroomt door de hele keten: van de aanroepplek van de hook, via de query-functie, tot de component die het resultaat consumeert. Geen as-casts, geen any-types.

Discriminated unions voor state machines

Complexe schermtoestanden — laden, fout, leeg, geladen — modelleer je het best als discriminated unions in plaats van een verzameling optionele velden:

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 hier string — TypeScript versmalt automatisch
      return <ErrorBanner message={state.error} retries={state.retryCount} />;
    case 'empty':
      return <EmptyState message={state.message} />;
    case 'loaded':
      // state.data is T — volledig getypeerd
      return renderItem(state.data);
  }
}

Dit patroon maakt onmogelijke toestanden onrepresenteerbaar. Een loading-toestand kan niet per ongeluk verouderde data meedragen, en een error-toestand bevat altijd context om te debuggen.

Vermijd gedeeltelijke state-objecten

Een veelvoorkomend anti-patroon: { isLoading: boolean; error?: string; data?: T }. Het staat toestanden toe als { isLoading: true, error: 'fail', data: [...] } — drie tegenstrijdige signalen tegelijk. Discriminated unions voorkomen dit op typeniveau.

Sollicitatievragen over React Native en TypeScript

Deze vragen weerspiegelen wat senior mobile-engineeringteams in sollicitatiegesprekken van 2026 stellen, nu de New Architecture en TypeScript de standaard zijn.

Hoe dwingt Codegen type-veiligheid af over de grens tussen JavaScript en native?

Codegen leest TypeScript- (of Flow-)specificatiebestanden en genereert daaruit interfacecode in C++, Objective-C++ en Java/Kotlin. De gegenereerde native interfaces dwingen exact de methodesignaturen, parametertypes en retourtypes af die in de specificatie zijn gedefinieerd. Wijkt de native implementatie af — door Int terug te geven waar de specificatie Double declareert, of een veld uit een struct weg te laten — dan weigert de native compiler de build. Dit verplaatst type-fouten van runtime-crashes naar fouten tijdens de build.

Wat is de Strict TypeScript API en waarom is die belangrijk?

De Strict TypeScript API, geïntroduceerd in React Native 0.80, genereert types direct uit de broncode van React Native in plaats van handgeschreven .d.ts-bestanden te onderhouden. Hij beperkt imports tot het root-pakket react-native en deprecieert diepe imports. Daarmee definieert hij een stabiel publiek API-oppervlak: interne refactors kunnen consumer-code niet breken zolang consumers alleen strikte types gebruiken. Inschakelen gebeurt via "types": ["react-native/types/strict"] in de tsconfig.json.

Hoe type je React Navigation-params over geneste navigators heen?

Definieer per navigator een ParamList-type en stel ze samen met NavigatorScreenParams. Voor een tab-navigator genest in een stack verwijst de param list van de stack naar die van de tab: type RootStack = { Main: NavigatorScreenParams<TabParamList>; Modal: { id: string } }. Elke navigate()-aanroep wordt dan typegecontroleerd door de volledige nestingshiërarchie, en vangt verkeerde schermnamen of ontbrekende params tijdens compilatie op.

Welk probleem lossen discriminated unions op in het state-management van React Native?

Discriminated unions modelleren elkaar uitsluitende toestanden (laden, fout, geladen) als afzonderlijke takken van een union-type, gekenmerkt door een status-veld. TypeScript versmalt het type in elke tak van een switch-statement, zodat toegang tot state.data alleen mogelijk is wanneer state.status === 'loaded'. Dit voorkomt onmogelijke toestanden zoals een laadindicator die naast foutdata wordt getoond — een categorie bugs die optionele velden en booleaanse flags niet kunnen voorkomen.

Leg het verschil uit tussen TurboModules en het oude Native Modules-systeem.

Native Modules communiceerden via de asynchrone bridge en serialiseerden alle data naar JSON. TurboModules gebruiken JSI (JavaScript Interface) voor synchrone, directe C++-aanroepen, zonder serialisatie-overhead. Ze laden bovendien lazy (bij het eerste gebruik in plaats van bij het opstarten van de app, wat de koudestarttijd verkort) en gebruiken Codegen om type-veilige interfaces te genereren uit TypeScript-specificaties. Het oude systeem leunde op het parsen van ReadableMap / NSDictionary met type-coercie tijdens runtime; TurboModules dwingen types af tijdens compilatie.

Voor meer sollicitatievragen over React Native behandelt de verdieping over native modules JSI, Fabric en de bridgeless architectuur in detail.

Begin met oefenen!

Test je kennis met onze gespreksimulatoren en technische tests.

Conclusie

  • De Strict TypeScript API (0.80+) beperkt imports tot het stabiele publieke oppervlak en voorkomt breuk door interne wijzigingen — schakel hem in elk nieuw project in
  • Codegen genereert native interfaces uit TypeScript-specificatiebestanden en verplaatst type-fouten over de grens tussen JS en native van runtime-crashes naar fouten tijdens de build
  • Getypeerde navigatie-params via RootStackParamList en NativeStackScreenProps vangen verkeerde schermnamen en ontbrekende params op voordat de app draait
  • Discriminated unions modelleren schermtoestanden als elkaar uitsluitende takken en maken onmogelijke toestanden op typeniveau onrepresenteerbaar
  • TurboModules met getypeerde specificaties vervangen het oude parsen van ReadableMap / NSDictionary en dwingen volledige type-veiligheid af van JavaScript via C++ tot platform-native code
  • Generieke API-hooks met TanStack Query behouden de type-inferentie van endpoint tot component zonder handmatige casts

Begin met oefenen!

Test je kennis met onze gespreksimulatoren en technische tests.

Tags

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

Delen

Gerelateerde artikelen