React Native y TypeScript en 2026: Arquitectura Type-Safe y Preguntas de Entrevista

Desarrollar aplicaciones React Native robustas con TypeScript, Codegen, TurboModules y la API Strict TypeScript. Arquitectura type-safe, navegación tipada y preguntas de entrevista técnica para 2026.

Arquitectura type-safe React Native TypeScript con código y dispositivos móviles

La seguridad de tipos en React Native alcanzó un nivel de madurez sin precedentes a mediados de 2026. Con la versión 0.86 publicada en junio, el framework incluye React 19.1, la API Strict TypeScript y una arquitectura completamente sin bridge impulsada por Codegen. TypeScript dejó de ser pegamento opcional entre JavaScript y el código nativo — ahora gobierna el contrato completo, desde las props de componentes hasta las interfaces de TurboModules, detectando incompatibilidades en tiempo de compilación en lugar de en los registros de errores de producción.

Qué cambió en 2026

React Native 0.80 introdujo la API Strict TypeScript de forma opt-in, la versión 0.82 eliminó permanentemente el bridge legacy, y 0.85 removió la última capa de interoperabilidad. A partir de la versión 0.86 (junio 2026), cada proyecto nuevo inicia en modo completamente bridgeless con tipos TypeScript generados directamente desde el código fuente.

Por qué TypeScript se convirtió en el estándar para proyectos React Native

Cada invocación de npx react-native init genera un proyecto TypeScript desde la versión 0.76. Pero el cambio real ocurrió en la frontera nativa. Antes de Codegen, los desarrolladores escribían aserciones de tipo manuales al cruzar de JavaScript a Objective-C o Kotlin — un contrato basado en cadenas de texto que fallaba silenciosamente en tiempo de ejecución. Codegen lee los archivos de especificación TypeScript y genera automáticamente las interfaces en C++, Objective-C++ y Java/Kotlin. Si la especificación TypeScript declara un método que retorna number, la interfaz nativa generada impone esa restricción en tiempo de compilación.

La documentación de React Native cubre la configuración básica, pero los patrones type-safe que importan en producción van más allá: pilas de navegación tipadas, hooks de API genéricos, uniones discriminadas para máquinas de estado, y especificaciones de TurboModules generadas por Codegen.

Configurar la API Strict TypeScript

La API Strict TypeScript, introducida en React Native 0.80, restringe la superficie de la API pública a los tipos generados directamente desde el código fuente. Esto previene la dependencia accidental de módulos internos que podrían romperse entre versiones menores.

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

Con esta configuración, importar cualquier cosa desde una subruta como react-native/Libraries/Text/Text genera un error de tipo. Todas las importaciones deben provenir del paquete raíz react-native, alineándose con la deprecación de importaciones profundas aplicada desde la versión 0.80.

React Navigation 7.x ofrece soporte TypeScript de primera clase. El patrón clave: definir un tipo RootStackParamList que asocia cada nombre de pantalla con sus parámetros esperados, y luego propagar ese tipo a través de navegadores y componentes de pantalla.

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

Los componentes de pantalla reciben props tipadas sin conversión manual:

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 es string — garantizado por el tipo
  // route.params.source es 'feed' | 'search' — sin verificación en runtime
  const { articleId, source } = route.params;

  // navigation.navigate('Profile', { userId: '123' }) — verificado por el compilador
  // navigation.navigate('Profile', {}) — error de compilación: falta userId
  return (
    <ArticleView id={articleId} referrer={source} />
  );
}

Este mecanismo elimina una clase completa de errores en tiempo de ejecución — navegar a una pantalla con parámetros incorrectos o faltantes falla en tiempo de compilación.

Tipado del hook useNavigation

Para componentes que no son hijos directos de una pantalla, utilizar useNavigation<NativeStackNavigationProp<RootStackParamList>>() proporciona la misma seguridad de tipos sin prop drilling.

Construir un TurboModule Type-Safe con Codegen

Los TurboModules reemplazan el sistema anterior de Native Modules. El archivo de especificación TypeScript funciona como la fuente única de verdad — Codegen genera las interfaces nativas a partir de él. Si la especificación y la implementación nativa divergen, el build falla.

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

La ejecución de npx react-native codegen genera las interfaces correspondientes en C++, Objective-C++ y Java. La implementación nativa debe coincidir exactamente con cada firma de método. Por ejemplo, getStorageInfo debe retornar un objeto con tres campos numéricos — retornar una estructura diferente provoca un error de compilación del lado nativo.

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

    // El tipo de retorno es impuesto por el NativeDeviceInfoSpec generado
    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)
    }
}

Este enfoque elimina el parsing de ReadableMap y NSDictionary que causaba bugs silenciosos de coerción de tipos en la arquitectura anterior.

¿Listo para aprobar tus entrevistas de React Native?

Practica con nuestros simuladores interactivos, flashcards y tests técnicos.

Hooks de API Genéricos con Tipado Completo

Un patrón de hook tipado reutilizable evita la duplicación de la lógica de fetch entre pantallas y al mismo tiempo preserva la inferencia de tipos completa:

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

// Uso — T se infiere como Article[]
interface Article {
  id: string;
  title: string;
  publishedAt: string;
}

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

El parámetro genérico T se propaga a través de toda la cadena: desde el punto de invocación del hook, a través de la función de consulta, hasta el componente que consume el resultado. Sin conversiones as, sin tipos any.

Uniones Discriminadas para Máquinas de Estado

Los estados complejos de pantalla — carga, error, vacío, cargado — se modelan mejor como uniones discriminadas en lugar de un conjunto de campos opcionales:

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 es string aquí — TypeScript reduce el tipo automáticamente
      return <ErrorBanner message={state.error} retries={state.retryCount} />;
    case 'empty':
      return <EmptyState message={state.message} />;
    case 'loaded':
      // state.data es T — completamente tipado
      return renderItem(state.data);
  }
}

Este patrón hace que los estados imposibles sean irrepresentables. Un estado loading no puede transportar accidentalmente datos obsoletos, y un estado error siempre incluye contexto para la depuración.

Evitar objetos de estado parciales

Un anti-patrón común: { isLoading: boolean; error?: string; data?: T }. Este esquema permite estados como { isLoading: true, error: 'fail', data: [...] } — tres señales contradictorias al mismo tiempo. Las uniones discriminadas previenen esto a nivel del sistema de tipos.

Preguntas de Entrevista React Native TypeScript

Estas preguntas reflejan lo que los equipos de ingeniería móvil senior preguntan en entrevistas en 2026, ahora que la New Architecture y TypeScript son el estándar.

¿Cómo impone Codegen la seguridad de tipos en la frontera JavaScript-nativo?

Codegen lee los archivos de especificación TypeScript (o Flow) y genera código de interfaz en C++, Objective-C++ y Java/Kotlin. Las interfaces nativas generadas imponen las firmas de métodos exactas, los tipos de parámetros y los tipos de retorno definidos en la especificación. Si la implementación nativa se desvía — retornando Int donde la especificación declara Double, u omitiendo un campo de una estructura — el compilador nativo rechaza el build. Esto traslada los errores de tipo de los crashes en runtime a fallos en tiempo de compilación.

¿Qué es la API Strict TypeScript y por qué es importante?

Introducida en React Native 0.80, la API Strict TypeScript genera los tipos directamente desde el código fuente de React Native en lugar de mantener archivos .d.ts escritos manualmente. Restringe las importaciones al paquete raíz react-native, deprecando las importaciones profundas. Esto define una superficie de API pública estable — las refactorizaciones internas no pueden romper el código del consumidor si este solo utiliza tipos estrictos. Se activa mediante "types": ["react-native/types/strict"] en tsconfig.json.

¿Cómo se tipan los parámetros de React Navigation a través de navegadores anidados?

Se define un tipo ParamList por navegador y se componen usando NavigatorScreenParams. Para un navegador de pestañas anidado dentro de una pila, la lista de parámetros de la pila referencia la de las pestañas: type RootStack = { Main: NavigatorScreenParams<TabParamList>; Modal: { id: string } }. Cada llamada navigate() se verifica a través de toda la jerarquía de anidamiento, detectando nombres de pantalla erróneos o parámetros faltantes en tiempo de compilación.

¿Qué problema resuelven las uniones discriminadas en el manejo de estado de React Native?

Las uniones discriminadas modelan estados mutuamente excluyentes (carga, error, cargado) como ramas separadas de un tipo unión, indexadas por un campo status. TypeScript reduce el tipo en cada rama de un switch, de modo que acceder a state.data solo es posible cuando state.status === 'loaded'. Esto previene estados imposibles como un indicador de carga mostrándose junto con datos de error — una clase de bugs que los campos opcionales y los flags booleanos no pueden prevenir.

Explicar la diferencia entre TurboModules y el antiguo sistema de Native Modules.

Los Native Modules se comunicaban a través del bridge asíncrono, serializando todos los datos a JSON. Los TurboModules utilizan JSI (JavaScript Interface) para llamadas C++ directas y síncronas — sin sobrecarga de serialización. También se cargan de forma lazy (al primer uso en lugar del inicio de la aplicación, reduciendo el tiempo de arranque en frío) y utilizan Codegen para generar interfaces type-safe desde las especificaciones TypeScript. El sistema anterior dependía del parsing de ReadableMap / NSDictionary con coerción de tipos en runtime; los TurboModules imponen los tipos en tiempo de compilación.

Para más preguntas de entrevista React Native, la guía detallada sobre módulos nativos cubre JSI, Fabric y la arquitectura bridgeless en profundidad.

¡Empieza a practicar!

Pon a prueba tu conocimiento con nuestros simuladores de entrevista y tests técnicos.

Conclusión

  • La API Strict TypeScript (0.80+) restringe las importaciones a la superficie pública estable, previniendo rupturas causadas por cambios internos — debe activarse en cada proyecto nuevo
  • Codegen genera las interfaces nativas desde los archivos de especificación TypeScript, trasladando los errores de tipo de los crashes en runtime a fallos de compilación en la frontera JS-nativo
  • Los parámetros de navegación tipados mediante RootStackParamList y NativeStackScreenProps detectan nombres de pantalla erróneos y parámetros faltantes antes de que la aplicación se ejecute
  • Las uniones discriminadas modelan los estados de pantalla como ramas mutuamente excluyentes, haciendo los estados imposibles irrepresentables a nivel del sistema de tipos
  • Los TurboModules con especificaciones tipadas reemplazan el antiguo parsing de ReadableMap / NSDictionary, imponiendo seguridad de tipos completa desde JavaScript a través de C++ hasta el código nativo de la plataforma
  • Los hooks de API genéricos con TanStack Query preservan la inferencia de tipos desde el endpoint hasta el componente sin conversiones manuales

¡Empieza a practicar!

Pon a prueba tu conocimiento con nuestros simuladores de entrevista y tests técnicos.

Etiquetas

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

Compartir

Artículos relacionados