0Pricing
TypeScript Academy · レッスン

ジェネリクスと推論を使ったカスタムフック

値、結果、エラーに を使った再利用可能なカスタムフックを記述し、推論と制約で安全なAPIを実現します

「ジェネリクスと推論を使ったカスタムフック」はCoddyKit上の無料TypeScript Academyレッスンです。 これはレッスン1/2です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはTypeScript Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 TypeScript Academyコースには全2レッスンが含まれています。

導入

目標: ネイティブ API のように使えるジェネリックなフックを作成します。型付きの localStorage フック、非同期ローダー、controlled/uncontrolled 用ヘルパーを実装します。呼び出し側で型注釈がほとんど不要になるよう、推論を活用します。

  • React のような使い勝手のためにタプルを返す
  • 必要に応じて制約を使う
  • any を使わない

useLocalStorage<T>

useState のように [value, set] というタプルを返します。value と setter の間で 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>

value、error、loading を持つオブジェクトを返します。value の型は、fn が返す promise から推論されます。

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>

1 つのヘルパーで controlled と uncontrolled の両方のパターンをサポートします。タプルによって 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 フックに最も適したシグネチャはどれですか。

まとめ

まとめ: 推論に依存するジェネリックなフックを作り、必要な場合にだけ制約を使い、ネイティブ React API のように使えるタプルやオブジェクトの結果を公開しました。

よくある質問

「ジェネリクスと推論を使ったカスタムフック」レッスンは無料ですか?

はい。「ジェネリクスと推論を使ったカスタムフック」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、TypeScript Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 TypeScript Academyコースには全2レッスンが含まれています。

「ジェネリクスと推論を使ったカスタムフック」で何を学びますか?

値、結果、エラーに を使った再利用可能なカスタムフックを記述し、推論と制約で安全なAPIを実現します ブラウザで直接実行するハンズオンコードでTypeScript Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

TypeScript Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのTypeScript Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/2です。

「ジェネリクスと推論を使ったカスタムフック」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このTypeScript Academyレッスンでコードを書いて実行できますか?

はい。すべてのTypeScript Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. ジェネリクスと推論を使ったカスタムフック
  2. SuspenseとError Boundaryの型
← TypeScript Academyに戻る