# 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. - Published: 2026-06-16 - Updated: 2026-06-17 - Author: SharpSkill - Tags: react-native, typescript, mobile-development, new-architecture, turbomodules - Reading time: 9 min --- 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. > **Cosa è cambiato nel 2026** > > 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](https://reactnative.dev/docs/typescript) 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. ```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" } ``` 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](https://reactnavigation.org/docs/typescript/) 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. ```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; }; ``` I componenti schermata ricevono così props tipizzate senza cast manuali: ```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 è 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 ( ); } ``` Questo elimina un'intera categoria di errori a runtime: navigare verso una schermata con parametri errati o mancanti fallisce già a tempo di build. > **Tipizzare l'hook useNavigation** > > Per i componenti che non sono figli diretti di una schermata, `useNavigation>()` 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. ```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'); ``` 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. ```kotlin // android/app/src/main/java/com/app/DeviceInfoModule.kt class DeviceInfoModule(reactContext: ReactApplicationContext) : NativeDeviceInfoSpec(reactContext) { // Tipo di ritorno imposto da NativeDeviceInfoSpec generato 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) } } ``` Questo approccio elimina il parsing di `ReadableMap` e `NSDictionary` che causava bug silenziosi di coercizione dei tipi nella vecchia architettura. ## 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: ```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, }); } // Utilizzo — T viene inferito come Article[] interface Article { id: string; title: string; publishedAt: string; } const { data, isLoading } = useApiQuery( ['articles', 'latest'], '/articles?sort=latest' ); // data.data è Article[] — completamente tipizzato // data.meta.totalPages è number ``` Il 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: ```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': // qui state.error è string — TypeScript restringe automaticamente return ; case 'empty': return ; 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. > **Evitare gli oggetti di stato parziali** > > 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; 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](/technologies/react-native/interview-questions/rn-native-modules), l'approfondimento sui native modules tratta in dettaglio JSI, Fabric e l'architettura bridgeless. ## 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 `RootStackParamList` e `NativeStackScreenProps` intercettano 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](https://tanstack.com/query/latest) preservano l'inferenza dei tipi dall'endpoint al componente senza cast manuali --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/it/blog/react-native/react-native-typescript-type-safe-architecture