React Native та TypeScript у 2026: Типобезпечна архітектура та питання співбесіди
Створення типобезпечних React Native додатків з TypeScript, Codegen, TurboModules та Strict TypeScript API. Охоплює патерни архітектури, типізовану навігацію, вимоги toolchain для 0.87 та питання співбесіди.

Типобезпека React Native TypeScript значно вдосконалилася до середини 2026 року, а версія 0.87 зробила Strict TypeScript API обов'язковим за замовчуванням і завершила масштабну модернізацію toolchain. TypeScript більше не є опціональним клеєм між JavaScript та native-кодом: він контролює весь контракт від пропсів компонентів до інтерфейсів TurboModule, виявляючи невідповідності на етапі збірки, а не в логах збоїв продакшену.
React Native 0.87 (серпень 2026) робить Strict TypeScript API обов'язковим за замовчуванням. Також підвищуються мінімальні вимоги до Node.js 22.13+, Kotlin 2.0+ та Android Gradle Plugin 9. Можливість відключення для застарілих deep imports залишається доступною лише до версії 0.88.
Чому TypeScript став стандартом для проєктів React Native
Кожен виклик npx react-native init з версії 0.76 створює TypeScript-проєкт. Але справжній зсув відбувся на межі з native-кодом. До Codegen розробники писали ручні type assertions при переході з JavaScript до Objective-C або Kotlin, що було слабко типізованим контрактом, який мовчки ламався в runtime. Codegen читає файли специфікацій TypeScript і автоматично генерує інтерфейси C++, Objective-C++ та Java/Kotlin. Якщо специфікація TypeScript оголошує метод, що повертає number, згенерований native-інтерфейс забезпечує це обмеження на етапі компіляції.
Документація React Native охоплює базове налаштування, але патерни типобезпеки, важливі для продакшену, йдуть далі: типізовані стеки навігації, generic API hooks, discriminated unions для state machines та специфікації TurboModule через Codegen.
Strict TypeScript API: від опції до стандарту
Strict TypeScript API було представлено в React Native 0.80 як opt-in функція. З версії 0.87 це обов'язковий стандарт для всіх нових проєктів. Типи генеруються безпосередньо з вихідного коду React Native замість ручного супроводу, усуваючи розбіжності між задокументованим API та фактичною реалізацією.
{
"extends": "@react-native/typescript-config",
"compilerOptions": {
"strict": true,
"exactOptionalPropertyTypes": true,
"noUncheckedIndexedAccess": true
}
}З цією конфігурацією імпорт чогось із підшляху на кшталт react-native/Libraries/Text/Text викликає помилку типу. Всі імпорти мають надходити з кореневого пакета react-native. Якщо бібліотека або застаріла кодова база все ще покладається на deep imports, тимчасове відключення доступне до версії 0.88:
{
"extends": "@react-native/typescript-config",
"compilerOptions": {
"customConditions": ["react-native", "react-native-legacy-deep-imports"]
}
}Це відключення буде видалено в 0.89. Міграцію слід виконати до того часу.
Вимоги toolchain у 0.87
React Native 0.87 підвищує мінімальні версії по всьому ланцюгу збірки:
| Компонент | Мінімум |
|---|---|
| Node.js | 22.13.0 |
| Kotlin | 2.0 (включена: 2.2.0) |
| Android Gradle Plugin | 9.x |
| Android compileSdk | 34 (мін), 37 (target) |
Для Android AGP 9 потребує додаткової конфігурації:
# android/gradle.properties
android.builtInKotlin=false
android.newDsl=falseЦі вимоги стосуються всіх проєктів, що цілять на 0.87+. Посібник міграції на New Architecture охоплює ширший контекст цих змін.
Типобезпечна навігація з React Navigation 7
React Navigation 7.x забезпечує першокласну підтримку TypeScript. Ключовий патерн: визначити тип RootStackParamList, який відображає кожну назву екрана на очікувані параметри, а потім прокинути цей тип через навігатори та компоненти екранів.
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;
};Компоненти екранів отримують типізовані пропси без ручного приведення:
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} />
);
}Це усуває цілий клас помилок runtime: навігація до екрана з неправильними або відсутніми параметрами завершується помилкою на етапі збірки.
Для компонентів, що не є прямими дочірніми елементами екрана, використання useNavigation<NativeStackNavigationProp<RootStackParamList>>() забезпечує таку саму типобезпеку без prop drilling.
Створення типобезпечних TurboModule з Codegen
TurboModules замінюють стару систему Native Modules. Файл специфікації TypeScript слугує єдиним джерелом істини, а Codegen генерує з нього native-інтерфейси. Якщо специфікація і native-реалізація розходяться, збірка завершується помилкою.
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 генерує відповідні інтерфейси C++, Objective-C++ та Java. Native-реалізація має точно відповідати кожній сигнатурі методу. Наприклад, getStorageInfo має повертати об'єкт з трьома числовими полями; повернення іншої форми викликає помилку компіляції на native-стороні.
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)
}
}Цей підхід усуває парсинг ReadableMap та NSDictionary, який спричиняв мовчазні помилки приведення типів у старій архітектурі. Глибший огляд системи native-модулів доступний у питаннях співбесіди про native modules.
Готовий до співбесід з React Native?
Практикуйся з нашими інтерактивними симуляторами, flashcards та технічними тестами.
Generic завантаження даних з типізованими API-хуками
Патерн багаторазового типізованого хука дозволяє уникнути дублювання логіки fetch між екранами, зберігаючи повну інференцію типів:
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 numberGeneric-параметр T протікає через весь ланцюг: від місця виклику хука, через функцію запиту, до компонента, що споживає результат. Жодних приведень as, жодних типів any.
Discriminated unions для state machines
Складні стани екрана (loading, error, empty, loaded) найкраще моделювати як discriminated unions замість набору опціональних полів:
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);
}
}Цей патерн робить неможливі стани непредставними. Стан loading не може випадково містити застарілі data, а стан error завжди включає контекст для відлагодження.
Поширений антипатерн: { isLoading: boolean; error?: string; data?: T }. Це дозволяє стани на кшталт { isLoading: true, error: 'fail', data: [...] }, три суперечливі сигнали одночасно. Discriminated unions запобігають цьому на рівні типів.
Питання співбесіди React Native TypeScript
Ці питання відображають те, що запитують команди senior mobile engineering на співбесідах у 2026 році, коли New Architecture та TypeScript є стандартом.
Як Codegen забезпечує типобезпеку на межі JavaScript-native?
Codegen читає файли специфікацій TypeScript (або Flow) і генерує код інтерфейсів C++, Objective-C++ та Java/Kotlin. Згенеровані native-інтерфейси забезпечують точні сигнатури методів, типи параметрів і типи повернення, визначені в специфікації. Якщо native-реалізація відхиляється (повертає Int де специфікація оголошує Double, або пропускає поле зі структури), native-компілятор відхиляє збірку. Це переносить помилки типів з runtime-збоїв до помилок збірки.
Що таке Strict TypeScript API і чому воно важливе?
Strict TypeScript API генерує типи безпосередньо з вихідного коду React Native замість супроводу вручну написаних файлів .d.ts. У версії 0.87 воно стало обов'язковим за замовчуванням. Воно обмежує імпорти до кореневого пакета react-native, deprecate'ячи deep imports. Це визначає стабільну публічну API-поверхню: внутрішні рефакторинги не можуть зламати споживчий код, якщо споживачі використовують лише strict types. Тимчасове відключення через customConditions залишається доступним до версії 0.88.
Як типізувати параметри React Navigation між вкладеними навігаторами?
Визначається тип ParamList для кожного навігатора і вони композуються за допомогою NavigatorScreenParams. Для tab-навігатора, вкладеного в stack, param list stack'а посилається на tab: type RootStack = { Main: NavigatorScreenParams<TabParamList>; Modal: { id: string } }. Кожен виклик navigate() перевіряється на типи через всю ієрархію вкладеності, виявляючи неправильні назви екранів або відсутні параметри на етапі компіляції.
Яку проблему вирішують discriminated unions в управлінні станом React Native?
Discriminated unions моделюють взаємовиключні стани (loading, error, loaded) як окремі гілки типу union, ключовані полем status. TypeScript звужує тип у кожній гілці оператора switch, тому доступ до state.data можливий лише коли state.status === 'loaded'. Це запобігає неможливим станам, як-от показ індикатора завантаження поряд з даними помилки, клас помилок, який опціональні поля та boolean-прапорці не можуть запобігти.
Поясніть різницю між TurboModules та старою системою Native Modules.
Native Modules спілкувалися через асинхронний bridge, серіалізуючи всі дані в JSON. TurboModules використовують JSI (JavaScript Interface) для синхронних, прямих викликів C++ без накладних витрат серіалізації. Вони також завантажуються ліниво (при першому використанні замість запуску додатку, зменшуючи час холодного старту) і використовують Codegen для генерації типобезпечних інтерфейсів зі специфікацій TypeScript. Стара система покладалася на парсинг ReadableMap / NSDictionary з приведенням типів у runtime; TurboModules забезпечують типи на етапі компіляції.
Які API були видалені в React Native 0.87?
Версія 0.87 видалила InteractionManager (використовуйте requestIdleCallback), типи NativeMethods / NativeMethodsMixin (використовуйте HostInstance) та кілька пропсів StatusBar. Deep imports до шляхів src/private/ тепер є помилками типів. Прапорець useTurboModules також видалено, оскільки TurboModules тепер завжди увімкнені.
Більше питань співбесіди React Native у повному посібнику, що охоплює архітектуру, продуктивність та відлагодження.
Починай практикувати!
Перевір свої знання з нашими симуляторами співбесід та технічними тестами.
Джерела
- React Native 0.87 Release Notes - Strict TypeScript API за замовчуванням, вимоги toolchain, видалення API
- React Native TypeScript Documentation - Офіційний посібник налаштування TypeScript
- React Navigation TypeScript Guide - Патерни типізованої навігації
- TanStack Query Documentation - Завантаження даних з інференцією типів
Що запам'ятати про React Native TypeScript у 2026
- Strict TypeScript API (обов'язкове в 0.87) обмежує імпорти стабільною публічною поверхнею, запобігаючи поломкам через внутрішні зміни. Відключення для застарілих deep imports доступне лише до версії 0.88
- Codegen генерує native-інтерфейси з файлів специфікацій TypeScript, переносячи помилки типів з runtime-збоїв до помилок збірки через межу JS-native
- Мінімальні вимоги toolchain у 0.87: Node.js 22.13+, Kotlin 2.0+, AGP 9, compileSdk 34+
- Типізовані параметри навігації через
RootStackParamListтаNativeStackScreenPropsвиявляють неправильні назви екранів та відсутні параметри до запуску додатку - Discriminated unions моделюють стани екрана як взаємовиключні гілки, роблячи неможливі стани непредставними на рівні типів
- TurboModules з типізованими специфікаціями замінюють старий парсинг
ReadableMap/NSDictionary, забезпечуючи повну типобезпеку від JavaScript через C++ до platform-native коду - Generic API-хуки з TanStack Query зберігають інференцію типів від endpoint до компонента без ручних приведень
Починай практикувати!
Перевір свої знання з нашими симуляторами співбесід та технічними тестами.
Чи знайдеш ти помилку в React Native?
Справжній фрагмент коду, прихована помилка, одна спроба на день. Щоб спробувати, акаунт не потрібен.

Автор:
Anthony Fillion-MailletЗасновник SharpSkill
Fullstack-розробник понад 10 років. Керує SharpSkill і відповідає за все, що тут публікується.
Оновлено 25 серпня 2026 р.
Теги
Поділитися
Пов'язані статті

Нова Архітектура React Native у 2026: Hermes V1, Bridgeless Mode та Питання для Співбесід
Нова Архітектура React Native є стандартом у 2026 році з Hermes V1, Bridgeless Mode, TurboModules та Fabric. Глибокий аналіз приросту продуктивності, патернів міграції та ключових питань для співбесід.

Посібник з розробки додатків React Native 2026: Продакшн-застосунки та питання для співбесіди
Повний посібник з розробки продакшн-застосунків React Native у 2026 році, що охоплює Expo SDK 56, EAS Build, Hermes V1, Нову Архітектуру та підготовку до співбесід для розробників React Native.

React Native 0.87 та SwiftPM у 2026: Сучасний iOS Build та Питання для Співбесід
React Native 0.87 впроваджує експериментальну підтримку Swift Package Manager, усуваючи потребу в CocoaPods. Дізнайтеся про налаштування SwiftPM, автолінкування та підготовку до співбесід.