Genéricos, uniões discriminadas e contratos de props reutilizáveis transformam componentes React Native em APIs auto-documentadas. Tipos de props fortes capturam combinações inválidas em tempo de compilação - antes que elas apareçam como bugs de layout no iOS e Android.
Cartão de receita de referência rápida - pronto para copiar e colar.
import { Pressable, StyleSheet, Text, View, type ViewProps } from "react-native";// Contrato base reutilizável - layout compartilhado + testIDtype BoxProps = ViewProps & { testID?: string;};// União discriminada - apenas combinações de props válidas compilamtype StatusBadgeProps = | { variant: "success"; message: string } | { variant: "error"; message: string; onRetry: () => void } | { variant: "loading" };export function StatusBadge(props: StatusBadgeProps) { if (props.variant === "loading") { return <Text style={styles.muted}>Carregando…</Text>; } if (props.variant === "error") { return ( <View style={styles.row}> <Text style={styles.error}>{props.message}</Text> <Pressable onPress={props.onRetry}> <Text style={styles.link}>Tentar novamente</Text> </Pressable> </View> ); } return <Text style={styles.success}>{props.message}</Text>;}// Linha de lista genérica - T flui do chamador para renderItemtype ListProps<T> = BoxProps & { data: readonly T[]; keyExtractor: (item: T) => string; renderItem: (item: T) => React.ReactNode;};export function SimpleList<T>({ data, keyExtractor, renderItem, ...viewProps }: ListProps<T>) { return ( <View {...viewProps}> {data.map((item) => ( <View key={keyExtractor(item)}>{renderItem(item)}</View> ))} </View> );}
Quando usar isso: Você está construindo primitivas de UI compartilhadas, linhas de lista ou componentes orientados por variantes e deseja que o TypeScript rejeite combinações de props impossíveis antes do tempo de execução.
import type { ComponentProps, ReactElement, ReactNode } from "react";import { Pressable, Text, type TextProps, type ViewProps } from "react-native";// Herda props primitivas, substitui apenas o que você possuitype CardProps = ViewProps & { title: string; footer?: ReactNode;};// Extrai onPress do Pressable sem importar o tipo de valor manualmentetype IconButtonProps = Pick<ComponentProps<typeof Pressable>, "onPress" | "disabled"> & { label: string; icon: ReactElement;};// Children estritos - apenas nós de Texto permitidos dentro de um wrapper de tipografiatype TypographyProps = TextProps & { children: string | ReactElement<typeof Text>;};
Opcional tudo em props de variante - { variant?: "a" \| "b"; a?: string; b?: number } permite que os chamadores passem { variant: "a", b: 1 } sem erro. Correção: Use uma união discriminada com campos obrigatórios por ramo.
Duplicar tipos de onPress - Escrever manualmente (event: GestureResponderEvent) => void se desvia das atualizações do RN. Correção: Use PressableProps["onPress"] ou ComponentProps<typeof Pressable>["onPress"].
Casting de dados de lista genérica - data as Place[] dentro de uma lista compartilhada oculta erros do chamador. Correção: Empurre o genérico para o componente de lista: FlatList<Place>, SectionList<Place>.
Espalhar props desconhecidas em View - {...rest} de um tipo amplo pode passar chaves inválidas para views nativas. Correção: Use Omit para chaves conhecidas e tipifique rest como ViewProps ou um Pick restrito.
Tipos de objeto inline em cada componente - ({ name }: { name: string }) está bom uma vez; formas repetidas pertencem a um tipo nomeado. Correção: Exporte ProfileCardProps do mesmo arquivo que o componente.
Esquecer readonly em arrays - Props tipadas como T[] permitem que os chamadores façam .push() em arrays passados. Correção: Prefira readonly T[] para props de dados somente leitura.
Usar React.FC para código novo - children implícitos e peculiaridades legadas adicionam ruído no React 19. Correção: Digite o parâmetro de props diretamente em uma função nomeada.
Devo usar interface ou type para props de componentes?
Qualquer um funciona. Use interface quando esperar mesclagem de declaração ou extensão entre arquivos; use type para uniões, tipos mapeados e composições Omit/Pick. A consistência dentro de um sistema de design é mais importante do que a palavra-chave.
Como tipar children em componentes de função React 19?
Adicione children?: React.ReactNode ao seu tipo de props quando o componente renderizar um slot. Não confie em React.FC - não é mais o padrão recomendado. Para APIs mais rigorosas, restrinja para ReactElement ou um tipo de componente específico.
Qual é o tipo correto para props de estilo?
Use StyleProp<ViewStyle> em View, StyleProp<TextStyle> em Text e StyleProp<ImageStyle> em Image. Estes aceitam um objeto de estilo, arrays e entradas falsy condicionais (condition && styles.x).
Como uniões discriminadas são restritas dentro do JSX?
Restrinja no corpo da função com if (props.variant === "error") antes de retornar JSX. O TypeScript carrega o tipo restrito para esse ramo, então props.onRetry só é obrigatório quando variant é "error".
Como compartilhar props entre dois componentes semelhantes?
Extraia um tipo base (RowBaseProps) e intercale com tipos específicos de variante. Use Pick e Omit para reutilizar fatias de primitivas: Pick<PressableProps, "onPress" | "disabled">.
Devo exportar tipos de props de arquivos de componentes?
Exporte quando outros módulos envolverem ou estenderem o componente - telas de navegação, histórias do Storybook e auxiliares de teste se beneficiam de export type ListRowProps. Mantenha props auxiliares internas não exportadas.
Como tipar props de callback opcionais?
Use campos opcionais: onPress?: () => void. Quando o callback é necessário apenas para um ramo da união, coloque-o dentro desse ramo de uma união discriminada em vez de marcá-lo como opcional globalmente.
Armadilha: Por que espalhar props quebra o autocompletar?
{...rest} onde rest é tipado muito amplamente (por exemplo, Record<string, unknown>) perde a verificação de chave. Tipifique rest como Omit<CardProps, "title"> ou ViewProps para que apenas chaves nativas válidas sejam espalhadas.
Como tipar uniões de nomes de ícones?
Use uniões de literais de string ("star" | "pin") ou mapas as const:
Uniões literais capturam erros de digitação em tempo de compilação e impulsionam a exaustividade do switch.
Posso usar valores de parâmetro padrão com props tipadas?
Sim - function Counter({ initial = 0 }: { initial?: number }) é idiomático. Os padrões são aplicados em tempo de execução; o TypeScript ainda trata a prop como opcional no lado do chamador.
Como tipar children de render-prop?
type MeasureProps = { children: (size: { width: number; height: number }) => React.ReactNode;};
O retorno do callback deve ser ReactNode; use ReactElement apenas quando você exigir um único elemento.
Como a verificação estrita de nulos afeta as props?
Com strict: true, props opcionais são T | undefined. Use prop ?? fallback ou guardas explícitas. Evite asserções não nulas prop! em componentes - os chamadores podem omitir o campo.
Componentes de linha de lista devem usar memo com props tipadas?
Sim, quando as linhas são caras e recebem props estáveis. Combine memo com um tipo de props nomeado para que comparadores e testes permaneçam claros. Lambdas inline instáveis onPress={() => …} anulam a memoização.
Como estender props de componentes de terceiros?
Use ComponentProps<typeof ThirdPartyButton> ou o tipo de props exportado pelo pacote. Reexporte uma versão restrita com Omit se você ocultar algumas props upstream do seu sistema de design.