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フィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- PropsとComponent Return Typesの型付け
- TypeScriptでのEventsとRefsの型付け
- Generic ComponentsとUtility Types
- ContextとCustom Hooksの型付け