Hooks personalizados con genéricos e inferencia
Escriba hooks personalizados reutilizables con para valores, resultados y errores; aproveche la inferencia y las restricciones para crear API seguras.
Hooks personalizados con genéricos e inferencia es una lección gratuita de TypeScript Academy en CoddyKit. Esta es la lección 1 de 2. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de TypeScript Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de TypeScript Academy incluye 2 lecciones en total.
Introducción
Objetivo: Cree hooks genéricos que se comporten como los nativos: un hook de localStorage tipado, un cargador asíncrono y una utilidad para patrones controlados y no controlados. Se basará en la inferencia para que los llamadores rara vez tengan que anotar tipos.
- Devuelva tuplas para una ergonomía similar a la de React
- Use restricciones cuando sea necesario
- No use any
useLocalStorage<T>
Devuelva una tupla [value, set] como la de useState. Mantenga T coherente entre el valor y el setter.
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>
Devuelva un objeto con value, error y loading. El tipo de value se infiere a partir de la promesa devuelta 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>
Admite los patrones controlado y no controlado con una sola utilidad. La tupla mantiene T alineado.
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 })Inferencia y restricciones
Prefiera la inferencia a partir de los argumentos; añada restricciones con extends solo cuando el hook necesite 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")Consejos
Consejos:
- Devuelva tuplas para conseguir una experiencia similar a React y un tipado coherente.
- No use nunca
anyen las firmas públicas de los hooks. - Acepte actualizadores
(prev) => nextpara facilitar las transiciones de estado.
Comprobación del tipado de hooks
Comprobación rápida: ¿qué firma se ajusta mejor a un hook genérico de localStorage?
Resumen
Resumen: Ha creado hooks genéricos que se basan en la inferencia, usan restricciones solo cuando es necesario y exponen resultados en forma de tupla u objeto, como las API nativas de React.
Preguntas frecuentes
¿La lección «Hooks personalizados con genéricos e inferencia» es gratis?
Sí — el texto completo de «Hooks personalizados con genéricos e inferencia» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de TypeScript Academy, actualiza a CoddyKit PRO. El curso de TypeScript Academy incluye 2 lecciones en total.
¿Qué aprenderé en «Hooks personalizados con genéricos e inferencia»?
Escriba hooks personalizados reutilizables con para valores, resultados y errores; aproveche la inferencia y las restricciones para crear API seguras. Practicas TypeScript Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar TypeScript Academy?
No se requiere experiencia previa. TypeScript Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 2.
¿Cuánto tiempo toma la lección «Hooks personalizados con genéricos e inferencia»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de TypeScript Academy?
Sí. Cada lección de TypeScript Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Hooks personalizados con genéricos e inferencia
- Tipos de Suspense y límites de error