You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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状态的对象,两者类型完全不匹配。

修复方案

  1. 重新定义ThemeContextType为包含mode和toggle的接口,匹配Provider传递的value结构
  2. 为createContext提供符合新类型的默认值
  3. 修正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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 16:45:10