TypeScript: Padrões em React que Escalam em Produção
TypeScript não é sobre encher o código de tipos até o compilador parar de reclamar. Em projetos React de médio e grande porte, o objetivo é evitar bugs e deixar claro o que cada parte do sistema espera receber.
Depois de anos com React em produção (AEM, LGPD, produtos próprios), estes são os padrões que mais ajudam quando o time cresce.
1. Modele o domínio antes do componente
Em vez de
data: anyexport type PricePoint = { date: string value: number marketplace: 'amazon' | 'mercadolivre' | 'shopee' } export type ProductSummary = { id: string title: string currentPrice: number history: PricePoint[] }
O componente recebe
ProductSummary2. Use unions para estados de UI
Loading, erro, vazio e sucesso ficam mais seguros com um tipo que discrimina o estado:
type AsyncState<T> = | { status: 'idle' } | { status: 'loading' } | { status: 'error'; message: string } | { status: 'success'; data: T }
No JSX, um
switchneverdefaultdata3. Props claras, sem vários booleans
Prefira uma variante nomeada a cinco flags
truefalse// ❌ difícil de manter type ButtonProps = { primary?: boolean; danger?: boolean; ghost?: boolean } // ✅ claro e extensível type ButtonProps = { variant?: 'primary' | 'secondary' | 'ghost' | 'danger' size?: 'sm' | 'md' | 'lg' }
Em design systems, isso evita combinações inválidas (
primaryghost4. satisfies
e as const
para configs
satisfiesas constMenus, rotas e feature flags ficam tipados sem perder os valores literais:
const NAV_ITEMS = [ { href: 'expertise', key: 'expertise' }, { href: 'projects', key: 'projects' }, ] as const satisfies ReadonlyArray<{ href: string; key: string }>
Você mantém autocomplete e validação na definição.
5. Validação na borda da API (Zod ou similar)
TypeScript some depois do build. Validação em runtime na entrada da API protege a UI:
const ProductSchema = z.object({ id: z.string(), title: z.string(), currentPrice: z.number().nonnegative(), }) const product = ProductSchema.parse(await response.json())
Use especialmente com APIs de terceiros ou scraping, onde o payload pode mudar sem aviso.
Conclusão
TypeScript escala quando os tipos descrevem o contrato entre camadas — não quando são decoração no JSX.
Comece pelo domínio, modele estados assíncronos com unions, simplifique props e valide na entrada. O time ganha velocidade com mais confiança no deploy.
