React Native e TypeScript em 2026: Arquitetura Type-Safe e Perguntas de Entrevista

Construir aplicações React Native robustas com TypeScript, Codegen, TurboModules e a API Strict TypeScript. Arquitetura type-safe, navegação tipada e perguntas de entrevista técnica para 2026.

Arquitetura type-safe React Native TypeScript com código e dispositivos móveis

A segurança de tipos no React Native atingiu um patamar decisivo em meados de 2026. Com a versão 0.86 lançada em junho, o framework traz React 19.1, a API Strict TypeScript e uma arquitetura completamente sem bridge alimentada pelo Codegen. O TypeScript deixou de ser uma camada opcional entre JavaScript e código nativo — agora ele governa todo o contrato, desde as props de componentes até as interfaces de TurboModules, capturando incompatibilidades em tempo de compilação em vez de nos logs de crash em produção.

O que mudou em 2026

O React Native 0.80 introduziu a API Strict TypeScript como opt-in, a versão 0.82 removeu permanentemente a bridge legacy, e a 0.85 eliminou a última camada de interoperabilidade. A partir da versão 0.86 (junho de 2026), cada projeto novo inicia no modo completamente bridgeless com tipos TypeScript gerados diretamente a partir do código-fonte.

Por que o TypeScript se tornou o padrão para projetos React Native

Cada chamada de npx react-native init gera um projeto TypeScript desde a versão 0.76. Mas a mudança real aconteceu na fronteira nativa. Antes do Codegen, os desenvolvedores escreviam asserções de tipo manuais ao cruzar de JavaScript para Objective-C ou Kotlin — um contrato baseado em strings que falhava silenciosamente em tempo de execução. O Codegen lê os arquivos de especificação TypeScript e gera automaticamente as interfaces em C++, Objective-C++ e Java/Kotlin. Se a especificação TypeScript declara um método que retorna number, a interface nativa gerada impõe essa restrição em tempo de compilação.

A documentação do React Native cobre a configuração básica, mas os padrões type-safe que realmente importam em produção vão além: pilhas de navegação tipadas, hooks de API genéricos, uniões discriminadas para máquinas de estado e especificações de TurboModules geradas pelo Codegen.

Configurando a API Strict TypeScript

A API Strict TypeScript, introduzida no React Native 0.80, restringe a superfície da API pública aos tipos gerados diretamente a partir do código-fonte. Isso impede a dependência acidental de módulos internos que podem quebrar entre versões 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"
}

Com essa configuração, importar qualquer coisa de um subcaminho como react-native/Libraries/Text/Text gera um erro de tipo. Todas as importações devem vir do pacote raiz react-native, alinhando-se com a depreciação de importações profundas aplicada desde a versão 0.80.

O React Navigation 7.x oferece suporte TypeScript de primeira classe. O padrão fundamental: definir um tipo RootStackParamList que mapeia cada nome de tela para seus parâmetros esperados e, em seguida, propagar esse tipo através dos navegadores e componentes de tela.

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

Os componentes de tela recebem props tipadas sem conversão 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 é string — garantido pelo tipo
  // route.params.source é 'feed' | 'search' — sem verificação em runtime
  const { articleId, source } = route.params;

  // navigation.navigate('Profile', { userId: '123' }) — verificado pelo compilador
  // navigation.navigate('Profile', {}) — erro de compilação: userId ausente
  return (
    <ArticleView id={articleId} referrer={source} />
  );
}

Esse mecanismo elimina uma classe inteira de erros em tempo de execução — navegar para uma tela com parâmetros incorretos ou ausentes falha em tempo de compilação.

Tipagem do hook useNavigation

Para componentes que não são filhos diretos de uma tela, utilizar useNavigation<NativeStackNavigationProp<RootStackParamList>>() fornece a mesma segurança de tipos sem prop drilling.

Construindo um TurboModule Type-Safe com Codegen

Os TurboModules substituem o antigo sistema de Native Modules. O arquivo de especificação TypeScript serve como a fonte única de verdade — o Codegen gera as interfaces nativas a partir dele. Se a especificação e a implementação nativa divergem, o build falha.

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

A execução de npx react-native codegen gera as interfaces correspondentes em C++, Objective-C++ e Java. A implementação nativa deve corresponder exatamente a cada assinatura de método. Por exemplo, getStorageInfo deve retornar um objeto com três campos numéricos — retornar uma estrutura diferente causa um erro de compilação no lado nativo.

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

    // O tipo de retorno é imposto pelo NativeDeviceInfoSpec gerado
    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)
    }
}

Essa abordagem elimina o parsing de ReadableMap e NSDictionary que causava bugs silenciosos de coerção de tipos na arquitetura anterior.

Pronto para mandar bem nas entrevistas de React Native?

Pratique com nossos simuladores interativos, flashcards e testes tecnicos.

Hooks de API Genéricos com Tipagem Completa

Um padrão de hook tipado reutilizável evita a duplicação da lógica de fetch entre telas, preservando a inferência 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 é inferido como Article[]
interface Article {
  id: string;
  title: string;
  publishedAt: string;
}

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

O parâmetro genérico T se propaga por toda a cadeia: do ponto de chamada do hook, passando pela função de consulta, até o componente que consome o resultado. Sem casts as, sem tipos any.

Uniões Discriminadas para Máquinas de Estado

Estados de tela complexos — carregamento, erro, vazio, carregado — são melhor modelados como uniões discriminadas em vez de um conjunto de campos opcionais:

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 é string aqui — TypeScript restringe o tipo automaticamente
      return <ErrorBanner message={state.error} retries={state.retryCount} />;
    case 'empty':
      return <EmptyState message={state.message} />;
    case 'loaded':
      // state.data é T — completamente tipado
      return renderItem(state.data);
  }
}

Esse padrão torna os estados impossíveis irrepresentáveis. Um estado loading não pode carregar acidentalmente dados obsoletos, e um estado error sempre inclui contexto para depuração.

Evitar objetos de estado parciais

Um anti-padrão comum: { isLoading: boolean; error?: string; data?: T }. Esse esquema permite estados como { isLoading: true, error: 'fail', data: [...] } — três sinais contraditórios ao mesmo tempo. As uniões discriminadas previnem isso no nível do sistema de tipos.

Perguntas de Entrevista React Native TypeScript

Estas perguntas refletem o que as equipes de engenharia móvel senior perguntam em entrevistas em 2026, agora que a New Architecture e o TypeScript se tornaram padrão.

Como o Codegen garante a segurança de tipos na fronteira JavaScript-nativo?

O Codegen lê os arquivos de especificação TypeScript (ou Flow) e gera código de interface em C++, Objective-C++ e Java/Kotlin. As interfaces nativas geradas impõem as assinaturas de métodos exatas, os tipos de parâmetros e os tipos de retorno definidos na especificação. Se a implementação nativa divergir — retornando Int onde a especificação declara Double, ou omitindo um campo de uma struct — o compilador nativo rejeita o build. Isso move os erros de tipo dos crashes em runtime para falhas em tempo de compilação.

O que é a API Strict TypeScript e por que ela é importante?

Introduzida no React Native 0.80, a API Strict TypeScript gera os tipos diretamente a partir do código-fonte do React Native, em vez de manter arquivos .d.ts escritos manualmente. Ela restringe as importações ao pacote raiz react-native, depreciando importações profundas. Isso define uma superfície de API pública estável — refatorações internas não podem quebrar o código do consumidor se este utilizar apenas tipos estrictos. A ativação é feita via "types": ["react-native/types/strict"] no tsconfig.json.

Como tipar os parâmetros do React Navigation através de navegadores aninhados?

Define-se um tipo ParamList por navegador e compõem-se usando NavigatorScreenParams. Para um navegador de abas aninhado dentro de uma pilha, a lista de parâmetros da pilha referencia a das abas: type RootStack = { Main: NavigatorScreenParams<TabParamList>; Modal: { id: string } }. Cada chamada navigate() é verificada através de toda a hierarquia de aninhamento, capturando nomes de tela errados ou parâmetros ausentes em tempo de compilação.

Qual problema as uniões discriminadas resolvem no gerenciamento de estado do React Native?

As uniões discriminadas modelam estados mutuamente exclusivos (carregamento, erro, carregado) como branches separados de um tipo union, indexados por um campo status. O TypeScript restringe o tipo em cada branch de um switch, de modo que acessar state.data só é possível quando state.status === 'loaded'. Isso previne estados impossíveis como um indicador de carregamento sendo exibido junto com dados de erro — uma classe de bugs que campos opcionais e flags booleanos não conseguem prevenir.

Explicar a diferença entre TurboModules e o antigo sistema de Native Modules.

Os Native Modules se comunicavam através da bridge assíncrona, serializando todos os dados em JSON. Os TurboModules utilizam JSI (JavaScript Interface) para chamadas C++ diretas e síncronas — sem overhead de serialização. Eles também carregam de forma lazy (no primeiro uso em vez da inicialização do app, reduzindo o tempo de cold start) e utilizam o Codegen para gerar interfaces type-safe a partir das especificações TypeScript. O sistema anterior dependia do parsing de ReadableMap / NSDictionary com coerção de tipos em runtime; os TurboModules impõem os tipos em tempo de compilação.

Para mais perguntas de entrevista React Native, o guia detalhado sobre módulos nativos cobre JSI, Fabric e a arquitetura bridgeless em profundidade.

Comece a praticar!

Teste seus conhecimentos com nossos simuladores de entrevista e testes tecnicos.

Conclusão

  • A API Strict TypeScript (0.80+) restringe as importações à superfície pública estável, prevenindo quebras causadas por mudanças internas — deve ser ativada em cada projeto novo
  • O Codegen gera as interfaces nativas a partir dos arquivos de especificação TypeScript, movendo os erros de tipo dos crashes em runtime para falhas de compilação na fronteira JS-nativo
  • Os parâmetros de navegação tipados via RootStackParamList e NativeStackScreenProps capturam nomes de tela errados e parâmetros ausentes antes da execução da aplicação
  • As uniões discriminadas modelam os estados de tela como branches mutuamente exclusivos, tornando os estados impossíveis irrepresentáveis no nível do sistema de tipos
  • Os TurboModules com especificações tipadas substituem o antigo parsing de ReadableMap / NSDictionary, impondo segurança de tipos completa de JavaScript através de C++ até o código nativo da plataforma
  • Os hooks de API genéricos com TanStack Query preservam a inferência de tipos do endpoint ao componente sem casts manuais

Comece a praticar!

Teste seus conhecimentos com nossos simuladores de entrevista e testes tecnicos.

Tags

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

Compartilhar

Artigos relacionados