0Pricing
React Academy · レッスン

ContextとCustom Hooksの型付け

default valuesを備えたtyped contextを作成し、明示的なreturn typesを持つcustom hooksを記述します。

「ContextとCustom Hooksの型付け」はCoddyKit上の無料React Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはReact Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 React Academyコースには全4レッスンが含まれています。

createContextによる型付きContext

createContextにContextの型とデフォルト値を渡します。Provider内でのみContextを使う必要がある場合はデフォルト値にnullを使用し、ガードで処理します。

interface AuthContextType {
  user: User | null;
  login: (credentials: Credentials) => Promise<void>;
  logout: () => void;
}

const AuthContext = createContext<AuthContextType | null>(null);

ガードフックパターン

Contextを読み取り、Providerの外で使用された場合はエラーをスローするカスタムフックを作成します。これにより、呼び出し箇所ごとのnullチェックが不要になります。

export function useAuth(): AuthContextType {
  const ctx = useContext(AuthContext);
  if (!ctx) throw new Error('useAuth must be used within AuthProvider');
  return ctx;
}

Providerの型付け

Providerコンポーネントはchildrenをラップし、Contextの値を提供します。値のオブジェクトを明示的に型付けして、Contextの型と一致することをTypeScriptに検証させます。

export function AuthProvider({ children }: { children: React.ReactNode }) {
  const [user, setUser] = useState<User | null>(null);

  const login = async (creds: Credentials) => {
    const u = await apiLogin(creds);
    setUser(u);
  };

  const logout = () => setUser(null);

  return (
    <AuthContext.Provider value={{ user, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
}

デフォルト値を持つContext

適切なデフォルト値(テーマなど)が存在する場合は、Contextが決してnullにならず、ガードフックも不要になるように、それを直接createContextに渡します。

interface ThemeContextType { theme: 'light' | 'dark'; toggle: () => void; }

const ThemeContext = createContext<ThemeContextType>({
  theme: 'light',
  toggle: () => {},
});

export const useTheme = () => useContext(ThemeContext);

カスタムフックの戻り値の型付け

カスタムフックの戻り値の型を明示的に注釈するか、TypeScriptに推論させます。明示的な型はドキュメントの役割を果たし、意図しない構造の変更を防ぎます。

interface UseCounterReturn {
  count: number;
  increment: () => void;
  decrement: () => void;
  reset: () => void;
}

function useCounter(initial = 0): UseCounterReturn {
  const [count, setCount] = useState(initial);
  return {
    count,
    increment: () => setCount(c => c + 1),
    decrement: () => setCount(c => c - 1),
    reset: () => setCount(initial),
  };
}

タプルの戻り値の型

useStateのようにペアを返すフックでは、タプルを使用します。as constまたは明示的なタプル型で型付けすると、分割代入時に正しく推論されます。

function useToggle(initial = false): [boolean, () => void] {
  const [value, setValue] = useState(initial);
  const toggle = useCallback(() => setValue(v => !v), []);
  return [value, toggle];
}

// Destructuring correctly infers types:
const [isOpen, toggleOpen] = useToggle();

ジェネリックなカスタムフック

カスタムフックもジェネリックにできます。ジェネリックなuseLocalStorageフックを使うと、任意のシリアライズ可能な型を完全な型安全性で保存できます。

function useLocalStorage<T>(key: string, initialValue: T): [T, (val: T) => void] {
  const [stored, setStored] = useState<T>(() => {
    try {
      const item = localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch { return initialValue; }
  });

  const setValue = (val: T) => {
    setStored(val);
    localStorage.setItem(key, JSON.stringify(val));
  };

  return [stored, setValue];
}

useReducerの型付け

アクション型を判別可能なユニオンとして、状態の形をインターフェースとして定義します。TypeScriptが、reducerで有効なアクション型だけが使われるように検証します。

interface State { count: number; status: 'idle' | 'loading'; }
type Action =
  | { type: 'INCREMENT' }
  | { type: 'SET_STATUS'; payload: State['status'] };

function reducer(state: State, action: Action): State {
  switch (action.type) {
    case 'INCREMENT': return { ...state, count: state.count + 1 };
    case 'SET_STATUS': return { ...state, status: action.payload };
  }
}

const [state, dispatch] = useReducer(reducer, { count: 0, status: 'idle' });

useCallbackとuseMemoの型付け

TypeScriptは、ファクトリ関数からuseCallbackとuseMemoの型を推論します。推論できない場合にのみ、明示的に注釈を付けます。

const handleChange = useCallback(
  (e: React.ChangeEvent<HTMLInputElement>) => {
    onChange(e.target.value);
  },
  [onChange]
);

const sorted = useMemo(
  () => [...items].sort((a, b) => a.name.localeCompare(b.name)),
  [items]
); // inferred as typeof items

型付きContextセレクターパターン

型付きセレクターフックはセレクター関数を受け取り、必要な部分だけを返しながら、完全な型推論を維持します。

function useAuthSelector<T>(selector: (ctx: AuthContextType) => T): T {
  const ctx = useAuth();
  return selector(ctx);
}

// Usage — TypeScript infers User | null:
const user = useAuthSelector(ctx => ctx.user);

フックでanyを避ける

カスタムフックでは決してanyを使用しません。ジェネリック、型ガード付きのunknown、または具体的なインターフェースを使用して、型のつながりを維持します。

// Bad:
function useFetch(url: string): { data: any; loading: boolean } { ... }

// Good:
function useFetch<T>(url: string): { data: T | null; loading: boolean } {
  const [data, setData] = useState<T | null>(null);
  // ...
  return { data, loading };
}

クイックチェック

React Contextの型付けでガードフックパターンを使う目的は何ですか?

まとめ

明示的なインターフェースとnullをガードするフックでContextを型付けします。カスタムフックの戻り値にはインターフェースまたはタプル型で注釈を付け、再利用可能なフックにはジェネリックを使用します。また、無効なdispatchをコンパイル時に検出できるよう、useReducerのアクションを判別可能なユニオンで型付けします。

よくある質問

「ContextとCustom Hooksの型付け」レッスンは無料ですか?

はい。「ContextとCustom Hooksの型付け」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、React Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 React Academyコースには全4レッスンが含まれています。

「ContextとCustom Hooksの型付け」で何を学びますか?

default valuesを備えたtyped contextを作成し、明示的なreturn typesを持つcustom hooksを記述します。 ブラウザで直接実行するハンズオンコードでReact Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

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

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

「ContextとCustom Hooksの型付け」レッスンにはどのくらい時間がかかりますか?

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

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

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

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

  1. PropsとComponent Return Typesの型付け
  2. TypeScriptでのEventsとRefsの型付け
  3. Generic ComponentsとUtility Types
  4. ContextとCustom Hooksの型付け
← React Academyに戻る