0Pricing
TypeScript Academy · Aula

Hooks personalizados com genéricos e inferência

Escreva hooks personalizados reutilizáveis com para valores, resultados e erros; aproveite a inferência e as restrições para APIs seguras.

Hooks personalizados com genéricos e inferência é uma aula grátis de TypeScript Academy no CoddyKit. Esta é a aula 1 de 2. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de TypeScript Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de TypeScript Academy inclui 2 aulas no total.

Introdução

Objetivo: crie ganchos genéricos que pareçam nativos: um gancho tipado para localStorage, um carregador assíncrono e um auxiliar para padrões controlados e não controlados. Você dependerá da inferência para que os chamadores raramente precisem anotar tipos.

  • Retorne tuplas para uma ergonomia semelhante à do React
  • Use restrições quando necessário
  • Não use qualquer

useLocalStorage<T>

Retorne uma tupla [valor, set] como em useState. Mantenha T consistente entre o valor e a função de definição.

import { useEffect, useState } from "react"

export function useLocalStorage<T>(key: string, initial: T): [T, (v: T | ((prev: T) => T)) => void] {
  const [value, setValue] = useState<T>(() => {
    try {
      const raw = localStorage.getItem(key)
      return raw ? (JSON.parse(raw) as T) : initial
    } catch {
      return initial
    }
  })

  useEffect(() => {
    try { localStorage.setItem(key, JSON.stringify(value)) } catch {}
  }, [key, value])

  const set = (v: T | ((prev: T) => T)) => {
    setValue(prev => (typeof v === "function" ? (v as (p: T) => T)(prev) : v))
  }

  return [value, set]
}

// Usage
// const [user, setUser] = useLocalStorage("user", { id: 1, name: "Ada" })

useAsync<T>

Retorne um objeto com valor, erro e carregando. O tipo de value é inferido a partir da promessa retornada por fn.

import { useEffect, useState } from "react"

export function useAsync<T>(fn: () => Promise<T>, deps: unknown[] = []) {
  const [value, setValue] = useState<T | null>(null)
  const [error, setError] = useState<unknown>(null)
  const [loading, setLoading] = useState<boolean>(false)

  useEffect(() => {
    let cancelled = false
    setLoading(true)
    fn().then(
      (v) => { if (!cancelled) { setValue(v); setError(null) } },
      (e) => { if (!cancelled) { setError(e); setValue(null) } }
    ).finally(() => { if (!cancelled) setLoading(false) })
    return () => { cancelled = true }
  }, deps)

  return { value, error, loading }
}

// Usage
// const { value, error, loading } = useAsync(() => fetch("/api").then(r => r.json()))

useControlled<T>

Ofereça suporte aos padrões controlado e não controlado com um único auxiliar. A tupla mantém T alinhado.

import { useState } from "react"

type ControlledProps<T> = {
  value?: T
  defaultValue: T
  onChange?: (v: T) => void
}

export function useControlled<T>({ value, defaultValue, onChange }: ControlledProps<T>): [T, (v: T) => void] {
  const [inner, setInner] = useState<T>(defaultValue)
  const isControlled = value !== undefined
  const current = isControlled ? (value as T) : inner
  const set = (v: T) => { isControlled ? onChange?.(v) : setInner(v) }
  return [current, set]
}

// Usage
// const [v, setV] = useControlled({ value, defaultValue: "", onChange: setValue })

Inferência e restrições

Prefira a inferência a partir dos argumentos; adicione restrições extends apenas quando o seu gancho precisar de campos específicos.

// Inference works from the initial value
const [settings, setSettings] = useLocalStorage("settings", { theme: "dark", pageSize: 20 })
// T = { theme: string; pageSize: number }

// Constrain T when needed
interface WithId { id: string }
function useById<T extends WithId>(items: T[], id: string) {
  return items.find(x => x.id === id) || null
}

// Usage
const user = useById([{ id: "u1", name: "Ada" }], "u1")

Dicas

Dicas:

  • Retorne tuplas para obter uma experiência semelhante à do React e uma tipagem consistente.
  • Nunca use any nas assinaturas públicas de ganchos.
  • Aceite funções de atualização (prev) => next para transições de estado mais práticas.

Verificação da tipagem de ganchos

Verificação rápida: qual assinatura se ajusta melhor a um gancho genérico para localStorage?

Recapitulação

Recapitulação: você criou ganchos genéricos que dependem da inferência, usam restrições apenas quando necessário e expõem resultados em tuplas ou objetos que se comportam como APIs nativas do React.

Perguntas Frequentes

A aula “Hooks personalizados com genéricos e inferência” é grátis?

Sim — o texto completo de “Hooks personalizados com genéricos e inferência” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de TypeScript Academy, atualize para CoddyKit PRO. O curso de TypeScript Academy inclui 2 aulas no total.

O que vou aprender em “Hooks personalizados com genéricos e inferência”?

Escreva hooks personalizados reutilizáveis com para valores, resultados e erros; aproveite a inferência e as restrições para APIs seguras. Você pratica TypeScript Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar TypeScript Academy?

Nenhuma experiência prévia é necessária. TypeScript Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 2.

Quanto tempo leva a aula “Hooks personalizados com genéricos e inferência”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de TypeScript Academy?

Sim. Cada aula de TypeScript Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Hooks personalizados com genéricos e inferência
  2. Tipos de Suspense e limites de erro
← Voltar para TypeScript Academy