React Native i TypeScript w 2026: Typobezpieczna architektura i pytania rekrutacyjne
Tworzenie typobezpiecznych aplikacji React Native z TypeScriptem, Codegen, TurboModules i Strict TypeScript API. Obejmuje wzorce architektury, typowaną nawigację, wymagania toolchain dla 0.87 oraz pytania rekrutacyjne.

React Native TypeScript stał się standardem branżowym w 2026 roku, a wersja 0.87 czyni Strict TypeScript API obowiązkowym domyślnym ustawieniem, kończąc proces modernizacji toolchain. TypeScript nie jest już opcjonalnym klejem między JavaScriptem a kodem natywnym: kontroluje cały kontrakt od propsów komponentów po interfejsy TurboModules, wyłapując niezgodności na etapie budowania zamiast w logach crashów produkcyjnych.
React Native 0.87 (sierpień 2026) czyni Strict TypeScript API obowiązkowym domyślnym ustawieniem. Podnosi również minimalne wymagania do Node.js 22.13+, Kotlin 2.0+ oraz Android Gradle Plugin 9. Możliwość wyłączenia dla starszych deep imports pozostaje dostępna tylko do wersji 0.88.
Dlaczego TypeScript jest standardem dla React Native
Każde wywołanie npx react-native init od wersji 0.76 tworzy projekt TypeScript. Prawdziwa zmiana nastąpiła jednak na granicy z kodem natywnym. Przed Codegen deweloperzy pisali ręczne asercje typów przy przekraczaniu granicy z JavaScript do Objective-C lub Kotlin, co było słabo typowanym kontraktem psującym się cicho w runtime. Codegen czyta pliki specyfikacji TypeScript i automatycznie generuje interfejsy C++, Objective-C++ oraz Java/Kotlin. Jeśli specyfikacja TypeScript deklaruje metodę zwracającą number, wygenerowany interfejs natywny wymusza to ograniczenie na etapie kompilacji.
Dokumentacja React Native opisuje podstawową konfigurację, ale wzorce typobezpieczeństwa istotne w produkcji idą dalej: typowane stosy nawigacji, generyczne hooki API, unie dyskryminowane dla maszyn stanów oraz specyfikacje TurboModules sterowane przez Codegen.
Strict TypeScript API: Od opcji do domyślnego ustawienia
Strict TypeScript API zostało wprowadzone w React Native 0.80 jako funkcja opt-in. Od wersji 0.87 jest obowiązkowym domyślnym ustawieniem dla wszystkich nowych projektów. Typy są generowane bezpośrednio z kodu źródłowego React Native zamiast być utrzymywane ręcznie, eliminując rozbieżności między dokumentowanym API a rzeczywistą implementacją.
{
"extends": "@react-native/typescript-config",
"compilerOptions": {
"strict": true,
"exactOptionalPropertyTypes": true,
"noUncheckedIndexedAccess": true
}
}Przy tej konfiguracji importowanie czegokolwiek ze ścieżki podrzędnej jak react-native/Libraries/Text/Text powoduje błąd typu. Wszystkie importy muszą pochodzić z głównego pakietu react-native. Jeśli biblioteka lub starsza baza kodu nadal polega na deep imports, tymczasowe wyłączenie jest dostępne do wersji 0.88:
{
"extends": "@react-native/typescript-config",
"compilerOptions": {
"customConditions": ["react-native", "react-native-legacy-deep-imports"]
}
}To wyłączenie zostanie usunięte w wersji 0.89. Migracja powinna nastąpić wcześniej.
Wymagania toolchain w 0.87
React Native 0.87 podnosi minimalne wersje w całym łańcuchu budowania:
| Komponent | Minimum |
|---|---|
| Node.js | 22.13.0 |
| Kotlin | 2.0 (dołączona: 2.2.0) |
| Android Gradle Plugin | 9.x |
| Android compileSdk | 34 (min), 37 (target) |
Dla Androida AGP 9 wymaga dodatkowej konfiguracji:
# android/gradle.properties
android.builtInKotlin=false
android.newDsl=falseTe wymagania dotyczą wszystkich projektów celujących w 0.87+. Przewodnik migracji do New Architecture opisuje szerszy kontekst tych zmian.
Typobezpieczna nawigacja z React Navigation 7
React Navigation 7.x zapewnia pierwszorzędne wsparcie TypeScript. Kluczowy wzorzec: zdefiniowanie typu RootStackParamList, który mapuje każdą nazwę ekranu na oczekiwane parametry, a następnie propagowanie tego typu przez nawigatory i komponenty ekranów.
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;
};Komponenty ekranów otrzymują następnie typowane propsy bez ręcznego rzutowania:
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} />
);
}To eliminuje całą klasę błędów runtime: nawigacja do ekranu z błędnymi lub brakującymi parametrami kończy się niepowodzeniem na etapie budowania.
Dla komponentów, które nie są bezpośrednimi dziećmi ekranu, użycie useNavigation<NativeStackNavigationProp<RootStackParamList>>() zapewnia to samo bezpieczeństwo typów bez prop drillingu.
Budowanie typobezpiecznych TurboModules z Codegen
TurboModules zastępują stary system Native Modules. Plik specyfikacji TypeScript służy jako jedyne źródło prawdy, a Codegen generuje z niego interfejsy natywne. Jeśli specyfikacja i implementacja natywna się rozmijają, budowanie kończy się niepowodzeniem.
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');Uruchomienie npx react-native codegen generuje odpowiednie interfejsy C++, Objective-C++ oraz Java. Implementacja natywna musi dokładnie odpowiadać każdej sygnaturze metody. Na przykład getStorageInfo musi zwracać obiekt z trzema polami numerycznymi; zwrócenie innego kształtu powoduje błąd kompilacji po stronie natywnej.
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)
}
}To podejście eliminuje parsowanie ReadableMap i NSDictionary, które powodowało ciche błędy koercji typów w starej architekturze. Głębsze spojrzenie na system modułów natywnych znajduje się w pytaniach rekrutacyjnych o native modules.
Gotowy na rozmowy o React Native?
Ćwicz z naszymi interaktywnymi symulatorami, flashcards i testami technicznymi.
Generyczne pobieranie danych z typowanymi hookami API
Wzorzec wielokrotnego użytku typowanego hooka pozwala uniknąć duplikacji logiki fetch między ekranami przy zachowaniu pełnej inferencji typów:
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 numberParametr generyczny T przepływa przez cały łańcuch: od miejsca wywołania hooka, przez funkcję zapytania, do komponentu konsumującego wynik. Żadnych rzutowań as, żadnych typów any.
Unie dyskryminowane dla maszyn stanów
Złożone stany ekranu (ładowanie, błąd, pusty, załadowany) najlepiej modelować jako unie dyskryminowane zamiast zbioru opcjonalnych pól:
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);
}
}Ten wzorzec sprawia, że niemożliwe stany są niereprezentowalne. Stan loading nie może przypadkowo zawierać przestarzałych data, a stan error zawsze zawiera kontekst do debugowania.
Częsty anty-wzorzec: { isLoading: boolean; error?: string; data?: T }. Pozwala to na stany takie jak { isLoading: true, error: 'fail', data: [...] }, trzy sprzeczne sygnały jednocześnie. Unie dyskryminowane zapobiegają temu na poziomie typów.
Pytania rekrutacyjne React Native TypeScript
Te pytania odzwierciedlają to, o co pytają zespoły senior mobile engineering na rozmowach kwalifikacyjnych w 2026 roku, gdy New Architecture i TypeScript są standardem.
Jak Codegen wymusza bezpieczeństwo typów na granicy JavaScript-natywny?
Codegen czyta pliki specyfikacji TypeScript (lub Flow) i generuje kod interfejsów C++, Objective-C++ oraz Java/Kotlin. Wygenerowane interfejsy natywne wymuszają dokładne sygnatury metod, typy parametrów i typy zwracane zdefiniowane w specyfikacji. Jeśli implementacja natywna odbiega (zwraca Int gdzie specyfikacja deklaruje Double, lub pomija pole w strukturze), kompilator natywny odrzuca budowanie. To przenosi błędy typów z crashów runtime na niepowodzenia budowania.
Czym jest Strict TypeScript API i dlaczego jest ważne?
Strict TypeScript API generuje typy bezpośrednio z kodu źródłowego React Native zamiast utrzymywania ręcznie pisanych plików .d.ts. W wersji 0.87 stało się obowiązkowym domyślnym ustawieniem. Ogranicza importy do głównego pakietu react-native, deprecjonując deep imports. Definiuje to stabilną publiczną powierzchnię API: wewnętrzne refaktoryzacje nie mogą złamać kodu konsumenta, jeśli konsumenci używają tylko strict types. Tymczasowe wyłączenie przez customConditions pozostaje dostępne do wersji 0.88.
Jak typować parametry React Navigation między zagnieżdżonymi nawigatorami?
Należy zdefiniować typ ParamList dla każdego nawigatora i złożyć je używając NavigatorScreenParams. Dla nawigatora tab zagnieżdżonego wewnątrz stack, lista parametrów stack odwołuje się do tab: type RootStack = { Main: NavigatorScreenParams<TabParamList>; Modal: { id: string } }. Każde wywołanie navigate() jest następnie sprawdzane pod kątem typów przez całą hierarchię zagnieżdżenia, wyłapując błędne nazwy ekranów lub brakujące parametry na etapie kompilacji.
Jaki problem rozwiązują unie dyskryminowane w zarządzaniu stanem React Native?
Unie dyskryminowane modelują wzajemnie wykluczające się stany (ładowanie, błąd, załadowany) jako oddzielne gałęzie typu unii, kluczowane przez pole status. TypeScript zawęża typ w każdej gałęzi instrukcji switch, więc dostęp do state.data jest możliwy tylko gdy state.status === 'loaded'. To zapobiega niemożliwym stanom jak wskaźnik ładowania pokazywany obok danych błędu, klasie błędów której opcjonalne pola i flagi boolowskie nie mogą zapobiec.
Wyjaśnij różnicę między TurboModules a starym systemem Native Modules.
Native Modules komunikowały się przez asynchroniczny bridge, serializując wszystkie dane do JSON. TurboModules używają JSI (JavaScript Interface) dla synchronicznych, bezpośrednich wywołań C++ bez narzutu serializacji. Ładują się również leniwie (przy pierwszym użyciu zamiast przy starcie aplikacji, redukując czas zimnego startu) i używają Codegen do generowania typobezpiecznych interfejsów ze specyfikacji TypeScript. Stary system polegał na parsowaniu ReadableMap / NSDictionary z koercją typów w runtime; TurboModules wymuszają typy na etapie kompilacji.
Jakie API zostały usunięte w React Native 0.87?
Wersja 0.87 usunęła InteractionManager (należy używać requestIdleCallback), typy NativeMethods / NativeMethodsMixin (należy używać HostInstance) oraz kilka propsów StatusBar. Deep imports do ścieżek src/private/ są teraz błędami typów. Flaga useTurboModules również została usunięta, ponieważ TurboModules są teraz zawsze włączone.
Więcej pytań rekrutacyjnych React Native w kompletnym przewodniku obejmującym architekturę, wydajność i debugowanie.
Zacznij ćwiczyć!
Sprawdź swoją wiedzę z naszymi symulatorami rozmów i testami technicznymi.
Źródła
- React Native 0.87 Release Notes - Strict TypeScript API domyślnie, wymagania toolchain, usunięcia API
- React Native TypeScript Documentation - Oficjalny przewodnik konfiguracji TypeScript
- React Navigation TypeScript Guide - Wzorce typowanej nawigacji
- TanStack Query Documentation - Pobieranie danych z inferencją typów
Co zapamiętać o React Native TypeScript w 2026
- Strict TypeScript API (obowiązkowe w 0.87) ogranicza importy do stabilnej publicznej powierzchni, zapobiegając uszkodzeniom przez wewnętrzne zmiany. Wyłączenie dla starszych deep imports jest dostępne tylko do wersji 0.88
- Codegen generuje interfejsy natywne z plików specyfikacji TypeScript, przenosząc błędy typów z crashów runtime na niepowodzenia budowania przez granicę JS-natywny
- Minimalne wymagania toolchain w 0.87: Node.js 22.13+, Kotlin 2.0+, AGP 9, compileSdk 34+
- Typowane parametry nawigacji przez
RootStackParamListiNativeStackScreenPropswyłapują błędne nazwy ekranów i brakujące parametry przed uruchomieniem aplikacji - Unie dyskryminowane modelują stany ekranu jako wzajemnie wykluczające się gałęzie, czyniąc niemożliwe stany niereprezentowalnymi na poziomie typów
- TurboModules z typowanymi specyfikacjami zastępują stare parsowanie
ReadableMap/NSDictionary, wymuszając pełne bezpieczeństwo typów od JavaScript przez C++ do kodu natywnego platformy - Generyczne hooki API z TanStack Query zachowują inferencję typów od endpointu do komponentu bez ręcznych rzutowań
Zacznij ćwiczyć!
Sprawdź swoją wiedzę z naszymi symulatorami rozmów i testami technicznymi.
Znajdziesz błąd w React Native?
Prawdziwy fragment kodu, ukryty błąd, jedna próba dziennie. Bez konta, żeby spróbować.

Autor:
Anthony Fillion-MailletZałożyciel SharpSkill
Programista fullstack od ponad 10 lat. Prowadzi SharpSkill i odpowiada za wszystko, co się tu ukazuje.
Zaktualizowano 25 sierpnia 2026
Tagi
Udostępnij
Powiązane artykuły

Nowa Architektura React Native w 2026: Hermes V1, Tryb Bridgeless i Pytania Rekrutacyjne
Nowa Architektura React Native jest domyślna w 2026 roku z Hermes V1, Trybem Bridgeless, TurboModules i Fabric. Głębokie omówienie zysków wydajnościowych, wzorców migracji i kluczowych pytań rekrutacyjnych.

Przewodnik po tworzeniu aplikacji React Native 2026: Produkcyjne aplikacje i pytania rekrutacyjne
Kompletny przewodnik po tworzeniu produkcyjnych aplikacji React Native w 2026 roku obejmujący Expo SDK 56, EAS Build, Hermes V1, Nową Architekturę oraz przygotowanie do rozmów kwalifikacyjnych dla programistów React Native.

React Native 0.87 i SwiftPM w 2026: Nowoczesny Build iOS i Pytania Rekrutacyjne
React Native 0.87 wprowadza eksperymentalne wsparcie dla Swift Package Manager, eliminując potrzebę CocoaPods. Poznaj konfigurację SwiftPM, autolinkowanie i przygotuj się do rozmów rekrutacyjnych.