Next.js中createContext暗黑模式的TypeScript类型不兼容问题
解决Next.js中TypeScript版ThemeContext类型不匹配问题
问题场景
将Next.js中用createContext实现的暗黑模式切换从JSX转为TypeScript时,ThemeContext.Provider的value属性出现类型错误:
Type '{ toggle: () => void; mode: string; }' is not assignable to type 'ThemeContextType'.ts(2322) index.d.ts(329, 9): The expected type comes from property 'value' which is declared here on type 'IntrinsicAttributes & ProviderProps<ThemeContextType>'
原代码:
"use client"; import { useState, createContext } from "react"; type ThemeContextType = "light" | "dark"; interface ChildrenProps { children: React.ReactNode; } export const ThemeContext = createContext<ThemeContextType>("light"); export const ThemeProvider = ({ children }: ChildrenProps) => { const [mode, setMode] = useState<string>("dark"); const toggle = (): void => { setMode((prev) => (prev === "dark" ? "light" : "dark")); }; return ( <ThemeContext.Provider value={{ toggle, mode }}> <div className={`theme ${mode}`}>{children}</div> </ThemeContext.Provider> ); };
错误原因
你定义的ThemeContextType只是表示主题模式的字符串字面量类型("light"|"dark"),但实际传给Provider的value是包含toggle函数和mode状态的对象,两者类型完全不匹配。
修复方案
- 重新定义
ThemeContextType为包含mode和toggle的接口,匹配Provider传递的value结构 - 为
createContext提供符合新类型的默认值 - 修正
useState的类型,避免使用宽泛的string,改用精确的主题模式类型
修复后的完整代码:
"use client"; import { useState, createContext, useContext } from "react"; // 重新定义Context类型,匹配Provider传递的value结构 interface ThemeContextType { mode: "light" | "dark"; toggle: () => void; } interface ChildrenProps { children: React.ReactNode; } // 提供符合类型的默认值 export const ThemeContext = createContext<ThemeContextType>({ mode: "light", toggle: () => {}, // 空函数作为默认实现 }); // 可选:封装useTheme钩子方便组件调用 export const useTheme = () => useContext(ThemeContext); export const ThemeProvider = ({ children }: ChildrenProps) => { // 使用精确的主题类型,替代宽泛的string const [mode, setMode] = useState<"light" | "dark">("dark"); const toggle = (): void => { setMode((prev) => (prev === "dark" ? "light" : "dark")); }; return ( <ThemeContext.Provider value={{ toggle, mode }}> <div className={`theme ${mode}`}>{children}</div> </ThemeContext.Provider> ); };
额外优化
- 封装
useTheme钩子,组件中可以直接通过const { mode, toggle } = useTheme()获取上下文,无需重复调用useContext - 给
useState指定精确的主题类型,避免类型宽泛导致的潜在问题
内容的提问来源于stack exchange,提问作者TungTung
相关产品推荐
相关产品推荐

