Hooks personnalisés avec génériques et inférence
Écrivez des hooks personnalisés réutilisables avec pour les valeurs, résultats et erreurs ; exploitez l’inférence et les contraintes pour des API sûres.
Hooks personnalisés avec génériques et inférence est une leçon TypeScript Academy gratuite sur CoddyKit. Ceci est la leçon 1 sur 2. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage TypeScript Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours TypeScript Academy comprend 2 leçons au total.
Introduction
Objectif : créez des hooks génériques qui semblent natifs : un hook typé pour localStorage, un chargeur asynchrone et un utilitaire contrôlé ou non contrôlé. Vous vous appuierez sur la déduction afin que les appelants aient rarement besoin d’annoter les types.
- Renvoyez des tuples pour une ergonomie semblable à celle de React
- Utilisez des contraintes lorsque nécessaire
- N’utilisez aucun type quelconque
useLocalStorage<T>
Renvoyez un tuple [value, set] comme avec useState. Gardez T cohérent entre la valeur et le 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>
Renvoyez un objet contenant une valeur, une erreur et un chargement. Le type de la value est déduit de la promesse renvoyée par 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>
Prenez en charge les modèles contrôlé et non contrôlé avec un seul utilitaire. Le tuple maintient la cohérence de T.
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 })Déduction et contraintes
Préférez la déduction à partir des arguments ; ajoutez des contraintes extends uniquement lorsque votre hook a besoin de champs précis.
// 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")Conseils
Conseils :
- Renvoyez des tuples pour une ergonomie proche de React et un typage cohérent.
- N’utilisez jamais
anydans les signatures publiques des hooks. - Acceptez les fonctions de mise à jour
(prev) => nextpour des transitions d’état ergonomiques.
Vérification du typage des hooks
Vérification rapide : quelle signature convient le mieux à un hook générique pour localStorage ?
Récapitulatif
Récapitulatif : vous avez créé des hooks génériques qui s’appuient sur la déduction, n’utilisent les contraintes que lorsque c’est nécessaire et exposent des résultats sous forme de tuple ou d’objet, comme les API natives de React.
Questions Fréquemment Posées
La leçon « Hooks personnalisés avec génériques et inférence » est-elle gratuite ?
Oui — le texte complet de « Hooks personnalisés avec génériques et inférence » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours TypeScript Academy, passe à CoddyKit PRO. Le cours TypeScript Academy comprend 2 leçons au total.
Qu'est-ce que j'apprendrai dans « Hooks personnalisés avec génériques et inférence » ?
Écrivez des hooks personnalisés réutilisables avec pour les valeurs, résultats et erreurs ; exploitez l’inférence et les contraintes pour des API sûres. Tu pratiques TypeScript Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer TypeScript Academy ?
Aucune expérience préalable n'est requise. TypeScript Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 1 sur 2.
Combien de temps prend la leçon « Hooks personnalisés avec génériques et inférence » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon TypeScript Academy ?
Oui. Chaque leçon TypeScript Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Hooks personnalisés avec génériques et inférence
- Types de Suspense et des frontières d’erreur