Пользовательские хуки с обобщениями и выводом типов
Пишите повторно используемые пользовательские хуки с для значений, результатов и ошибок; применяйте вывод типов и ограничения для безопасных API.
«Пользовательские хуки с обобщениями и выводом типов» — бесплатный урок TypeScript Academy на CoddyKit. Это урок 1 из 2. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения TypeScript Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс TypeScript Academy содержит 2 уроков всего.
Введение
Цель: создать обобщённые хуки, которые ощущаются как встроенные: типизированный хук для localStorage, асинхронный загрузчик и помощник для управляемого и неуправляемого режимов. Вы будете полагаться на вывод типов, поэтому вызывающему коду редко понадобятся аннотации.
- Возвращать кортежи для удобства в стиле React
- Использовать ограничения при необходимости
- Не использовать универсальный тип
useLocalStorage<T>
Возвращайте кортеж [значение, set], как в useState. Поддерживайте согласованность T между значением и функцией установки.
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>
Возвращайте объект со свойствами значение, ошибка, загрузка. Тип значения выводится из промиса, возвращаемого 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>
Поддерживайте управляемый и неуправляемый режимы с помощью одного помощника. Кортеж сохраняет согласованность 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 })Вывод типов и ограничения
Предпочитайте вывод типов из аргументов; добавляйте ограничения extends только тогда, когда хуку нужны определённые поля.
// 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")Советы
Советы:
- Возвращайте кортежи для удобства в стиле React и единообразной типизации.
- Никогда не используйте
anyв общедоступных сигнатурах хуков. - Принимайте функции обновления
(prev) => nextдля удобных переходов состояния.
Проверка типизации хуков
Быстрая проверка: какая сигнатура лучше всего подходит для обобщённого хука localStorage?
Повторение
Повторение: вы создали обобщённые хуки, использующие вывод типов, применяющие ограничения только при необходимости и предоставляющие результаты в виде кортежей или объектов, подобно встроенным API React.
Изучай TypeScript с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 101
- Уроки
- 352
Часто задаваемые вопросы
Урок «Пользовательские хуки с обобщениями и выводом типов» бесплатный?
Да — полный текст урока «Пользовательские хуки с обобщениями и выводом типов» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс TypeScript Academy, подпишись на CoddyKit PRO. Курс TypeScript Academy содержит 2 уроков всего.
Чему я научусь в уроке «Пользовательские хуки с обобщениями и выводом типов»?
Пишите повторно используемые пользовательские хуки с для значений, результатов и ошибок; применяйте вывод типов и ограничения для безопасных API. Ты практикуешь TypeScript Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать TypeScript Academy?
Предыдущий опыт не требуется. TypeScript Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 2.
Сколько времени занимает урок «Пользовательские хуки с обобщениями и выводом типов»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке TypeScript Academy?
Да. Каждый урок TypeScript Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Пользовательские хуки с обобщениями и выводом типов
- Типы Suspense и границ ошибок