React Native e TypeScript nel 2026: architettura type-safe e domande da colloquio
Crea app React Native type-safe con TypeScript, Codegen, TurboModule e la Strict TypeScript API. Pattern architetturali, navigazione tipizzata e domande da colloquio per il 2026.

La type safety di React Native con TypeScript è maturata in modo significativo a metà 2026: la versione 0.86 introduce React 19.1, la Strict TypeScript API e un'architettura completamente bridgeless basata su Codegen. TypeScript non è più una colla opzionale tra JavaScript e codice nativo: governa l'intero contratto, dalle props dei componenti alle interfacce dei TurboModule, intercettando le incoerenze a tempo di build invece che nei log di crash in produzione.
React Native 0.80 ha introdotto la Strict TypeScript API opzionale, la 0.82 ha rimosso definitivamente la vecchia bridge e la 0.85 ha eliminato l'ultimo livello di interop. Dalla 0.86 (giugno 2026), ogni nuovo progetto parte completamente bridgeless, con tipi TypeScript generati direttamente dal codice sorgente.
Perché TypeScript è ormai lo standard per i progetti React Native
Ogni invocazione di npx react-native init dalla versione 0.76 genera lo scaffold di un progetto TypeScript. Il vero cambiamento, però, è avvenuto al confine nativo. Prima di Codegen, gli sviluppatori scrivevano asserzioni di tipo manuali nel passaggio da JavaScript a Objective-C o Kotlin: un contratto basato su stringhe che si rompeva silenziosamente a runtime. Codegen legge i file di specifica TypeScript e genera automaticamente le interfacce C++, Objective-C++ e Java/Kotlin. Se la specifica TypeScript dichiara un metodo che restituisce number, l'interfaccia nativa generata impone quel vincolo a tempo di compilazione.
La documentazione di React Native copre la configurazione di base, ma i pattern type-safe che contano in produzione vanno oltre: stack di navigazione tipizzati, hook API generici, union discriminate per le state machine e specifiche TurboModule guidate da Codegen.
Configurare la Strict TypeScript API
La Strict TypeScript API, introdotta in React Native 0.80, limita la superficie dell'API pubblica ai tipi generati direttamente dal codice sorgente. Questo evita di dipendere accidentalmente da moduli interni che potrebbero rompersi tra versioni minor.
{
"compilerOptions": {
"strict": true,
"exactOptionalPropertyTypes": true,
"noUncheckedIndexedAccess": true,
"moduleResolution": "bundler",
"jsx": "react-jsx",
"types": ["react-native/types/strict"]
},
"extends": "@react-native/typescript-config/tsconfig.json"
}Con questa configurazione, importare qualcosa da un sottopercorso come react-native/Libraries/Text/Text genera un errore di tipo. Tutti gli import devono provenire dal pacchetto radice react-native, in linea con la deprecazione dei deep import applicata dalla 0.80.
Navigazione type-safe con React Navigation 7
React Navigation 7.x offre un supporto TypeScript di prima classe. Il pattern chiave: definire un tipo RootStackParamList che mappa ogni nome di schermata ai parametri attesi, poi propagare quel tipo attraverso i navigatori e i componenti schermata.
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;
};I componenti schermata ricevono così props tipizzate senza cast manuali:
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 è string — garantito dal tipo
// route.params.source è 'feed' | 'search' — nessun controllo a runtime
const { articleId, source } = route.params;
// navigation.navigate('Profile', { userId: '123' }) — verificato dai tipi
// navigation.navigate('Profile', {}) — errore di compilazione: manca userId
return (
<ArticleView id={articleId} referrer={source} />
);
}Questo elimina un'intera categoria di errori a runtime: navigare verso una schermata con parametri errati o mancanti fallisce già a tempo di build.
Per i componenti che non sono figli diretti di una schermata, useNavigation<NativeStackNavigationProp<RootStackParamList>>() fornisce la stessa type safety senza prop drilling.
Costruire un TurboModule type-safe con Codegen
I TurboModule sostituiscono il vecchio sistema dei Native Modules. Il file di specifica TypeScript funge da unica fonte di verità: Codegen genera da esso le interfacce native. Se specifica e implementazione nativa divergono, la build fallisce.
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');Eseguire npx react-native codegen genera le corrispondenti interfacce C++, Objective-C++ e Java. L'implementazione nativa deve rispettare esattamente ogni firma di metodo. Ad esempio, getStorageInfo deve restituire un oggetto con tre campi numerici: restituire una forma diversa causa un errore di compilazione sul lato nativo.
class DeviceInfoModule(reactContext: ReactApplicationContext) :
NativeDeviceInfoSpec(reactContext) {
// Tipo di ritorno imposto da NativeDeviceInfoSpec generato
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)
}
}Questo approccio elimina il parsing di ReadableMap e NSDictionary che causava bug silenziosi di coercizione dei tipi nella vecchia architettura.
Pronto a superare i tuoi colloqui su React Native?
Pratica con i nostri simulatori interattivi, flashcards e test tecnici.
Data fetching generico con hook API tipizzati
Un pattern di hook tipizzato e riutilizzabile evita di duplicare la logica di fetch tra le schermate preservando al contempo l'inferenza completa dei tipi:
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,
});
}
// Utilizzo — T viene inferito come Article[]
interface Article {
id: string;
title: string;
publishedAt: string;
}
const { data, isLoading } = useApiQuery<Article[]>(
['articles', 'latest'],
'/articles?sort=latest'
);
// data.data è Article[] — completamente tipizzato
// data.meta.totalPages è numberIl parametro generico T attraversa l'intera catena: dal punto di chiamata dell'hook, attraverso la funzione di query, fino al componente che consuma il risultato. Nessun cast as, nessun tipo any.
Union discriminate per le state machine
Gli stati complessi di una schermata — caricamento, errore, vuoto, caricato — si modellano al meglio come union discriminate, anziché come un insieme di campi opzionali:
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':
// qui state.error è string — TypeScript restringe automaticamente
return <ErrorBanner message={state.error} retries={state.retryCount} />;
case 'empty':
return <EmptyState message={state.message} />;
case 'loaded':
// state.data è T — completamente tipizzato
return renderItem(state.data);
}
}Questo pattern rende gli stati impossibili non rappresentabili. Uno stato loading non può portare accidentalmente data obsoleti e uno stato error include sempre il contesto per il debug.
Un anti-pattern comune: { isLoading: boolean; error?: string; data?: T }. Consente stati come { isLoading: true, error: 'fail', data: [...] } — tre segnali contraddittori contemporaneamente. Le union discriminate lo impediscono a livello di tipo.
Domande da colloquio su React Native e TypeScript
Queste domande riflettono ciò che i team di mobile engineering senior chiedono nei colloqui del 2026, ora che la New Architecture e TypeScript sono lo standard.
Come fa Codegen a imporre la type safety attraverso il confine JavaScript-nativo?
Codegen legge i file di specifica TypeScript (o Flow) e genera codice di interfaccia C++, Objective-C++ e Java/Kotlin. Le interfacce native generate impongono esattamente le firme dei metodi, i tipi dei parametri e i tipi di ritorno definiti nella specifica. Se l'implementazione nativa devia — restituendo Int dove la specifica dichiara Double, oppure omettendo un campo da una struct — il compilatore nativo rifiuta la build. Questo sposta gli errori di tipo dai crash a runtime ai fallimenti a tempo di build.
Cos'è la Strict TypeScript API e perché è importante?
Introdotta in React Native 0.80, la Strict TypeScript API genera i tipi direttamente dal codice sorgente di React Native invece di mantenere file .d.ts scritti a mano. Limita gli import al pacchetto radice react-native, deprecando i deep import. Questo definisce una superficie pubblica dell'API stabile: i refactoring interni non possono rompere il codice consumer finché questo usa solo i tipi strict. Si abilita tramite "types": ["react-native/types/strict"] nel tsconfig.json.
Come si tipizzano i parametri di React Navigation tra navigatori annidati?
Definire un tipo ParamList per ogni navigatore e comporli con NavigatorScreenParams. Per un tab navigator annidato dentro uno stack, la param list dello stack referenzia quella del tab: type RootStack = { Main: NavigatorScreenParams<TabParamList>; Modal: { id: string } }. Ogni chiamata navigate() viene così verificata dai tipi attraverso l'intera gerarchia di annidamento, intercettando nomi di schermata errati o parametri mancanti a tempo di compilazione.
Quale problema risolvono le union discriminate nello state management di React Native?
Le union discriminate modellano stati mutuamente esclusivi (caricamento, errore, caricato) come rami separati di un tipo union, distinti da un campo status. TypeScript restringe il tipo in ogni ramo di uno switch, così l'accesso a state.data è possibile solo quando state.status === 'loaded'. Questo evita stati impossibili come un indicatore di caricamento mostrato insieme a dati di errore, una categoria di bug che i campi opzionali e i flag booleani non riescono a prevenire.
Spiega la differenza tra i TurboModule e il vecchio sistema dei Native Modules.
I Native Modules comunicavano tramite la bridge asincrona, serializzando tutti i dati in JSON. I TurboModule usano JSI (JavaScript Interface) per chiamate C++ sincrone e dirette, senza overhead di serializzazione. Inoltre si caricano in modo lazy (al primo utilizzo invece che all'avvio dell'app, riducendo il tempo di cold start) e usano Codegen per generare interfacce type-safe dalle specifiche TypeScript. Il vecchio sistema si affidava al parsing di ReadableMap / NSDictionary con coercizione dei tipi a runtime; i TurboModule impongono i tipi a tempo di compilazione.
Per altre domande da colloquio su React Native, l'approfondimento sui native modules tratta in dettaglio JSI, Fabric e l'architettura bridgeless.
Inizia a praticare!
Metti alla prova le tue conoscenze con i nostri simulatori di colloquio e test tecnici.
Conclusione
- La Strict TypeScript API (0.80+) limita gli import alla superficie pubblica stabile, evitando rotture dovute a modifiche interne — va abilitata in ogni nuovo progetto
- Codegen genera le interfacce native dai file di specifica TypeScript, spostando gli errori di tipo dai crash a runtime ai fallimenti a tempo di build attraverso il confine JS-nativo
- I parametri di navigazione tipizzati via
RootStackParamListeNativeStackScreenPropsintercettano nomi di schermata errati e parametri mancanti prima che l'app venga eseguita - Le union discriminate modellano gli stati delle schermate come rami mutuamente esclusivi, rendendo gli stati impossibili non rappresentabili a livello di tipo
- I TurboModule con specifiche tipizzate sostituiscono il vecchio parsing di
ReadableMap/NSDictionary, imponendo type safety completa da JavaScript fino al codice nativo della piattaforma passando per il C++ - Gli hook API generici con TanStack Query preservano l'inferenza dei tipi dall'endpoint al componente senza cast manuali
Inizia a praticare!
Metti alla prova le tue conoscenze con i nostri simulatori di colloquio e test tecnici.
Tag
Condividi
Articoli correlati

React Native New Architecture nel 2026: Hermes V1, Bridgeless Mode e Domande per Colloqui
Analisi approfondita della React Native New Architecture con Hermes V1, Bridgeless Mode, TurboModules e Fabric Renderer. Benchmark di performance, guida alla migrazione e domande frequenti nei colloqui tecnici.

React Native 0.85 nel 2026: Nuovo Animation Backend, API TypeScript Strict e Domande da Colloquio
Analisi approfondita delle novità di React Native 0.85: Shared Animation Backend, architettura post-bridge con JSI e TurboModules, supporto Metro TLS e domande da colloquio tecnico aggiornate al 2026.

Expo Router in React Native: Guida Completa alla Navigazione File-Based
Guida completa a Expo Router per React Native nel 2026. Navigazione basata su file, route dinamiche, tab, modali, typed routes, middleware e protezione delle route con esempi di codice.