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

React Context中setJobData函数式更新触发TypeScript类型错误

排查React Context中setJobData函数式更新的TypeScript类型错误

问题场景

调用setJobData进行函数式更新时触发TypeScript类型错误,核心代码及错误信息如下:

核心代码

const { jobData, setJobData } = useJobCreation();

const handleSkillSelect = (skillKey: string) => {
  const skillIndex = jobData.skillSet.findIndex(
    skill => skill.key === skillKey,
  );
  if (skillIndex !== -1) {
    // 移除已选中的技能
    const updatedSkillSet = jobData.skillSet.filter(
      skill => skill.key !== skillKey,
    );
    setJobData((prevJobData: JobCreationType) => ({
      ...prevJobData,
      skillSet: updatedSkillSet,
    }));
  } else {
    // 添加未选中的技能
    const selectedSkill = filteredSkillsData.find(
      skill => skill.key === skillKey,
    );
    if (selectedSkill) {
      setJobData((prevJobData: JobCreationType) => ({
        ...prevJobData,
        skillSet: [...prevJobData.skillSet, selectedSkill],
      }));
    }
  }
};

触发的错误信息

Argument of type '(prevJobData: JobCreationType) => { skillSet: Skill[]; jobRequirements: string[]; customRequirements: CustomRequirement[]; jobDetails: JobDetails; }' is not assignable to parameter of type 'JobCreationType'.

简化测试代码的错误

执行setJobData(prevJobData => ({ ...prevJobData }))时,同样报错:

Parameter 'prevJobData' implicitly has an 'any' type.ts(7006) Argument of type '(prevJobData: any) => any' is not assignable to parameter of type 'JobCreationType'.

相关类型定义

export interface JobCreationType {
  skillSet: Skill[];
  jobRequirements: string[];
  customRequirements: CustomRequirement[];
  jobDetails: JobDetails;
}

错误原因

问题根源在于useJobCreation返回的setJobData类型定义错误——它仅被定义为接受JobCreationType类型的直接值,不支持函数式更新的签名。

React原生状态更新函数(如useState返回的setter)支持两种调用形式:

  1. 直接传入新状态值:setState(newValue)
  2. 传入接收前状态的函数:setState(prev => newState)

但你的Context中setJobData的类型未包含第二种形式,导致TypeScript判定传入的函数不符合参数要求。

解决方案

修正useJobCreation所在Context的类型定义,让setJobData同时支持两种更新方式:

步骤1:定义正确的setter类型

将setJobData的类型设置为React内置的React.Dispatch<React.SetStateAction<JobCreationType>>,该类型天然兼容两种更新形式:

// Context类型定义
interface JobCreationContextType {
  jobData: JobCreationType;
  setJobData: React.Dispatch<React.SetStateAction<JobCreationType>>;
}

// 创建Context并指定类型
const JobCreationContext = createContext<JobCreationContextType>({
  jobData: {
    skillSet: [],
    jobRequirements: [],
    customRequirements: [],
    jobDetails: {} as JobDetails // 根据实际场景设置初始值
  },
  setJobData: () => {} // 空占位符
});

步骤2:在Provider中传递正确的setter

确保Provider中setJobData是useState返回的原生setter(或符合该类型的自定义函数):

export const JobCreationProvider = ({ children }: { children: React.ReactNode }) => {
  const [jobData, setJobData] = useState<JobCreationType>({
    skillSet: [],
    jobRequirements: [],
    customRequirements: [],
    jobDetails: {} as JobDetails
  });

  return (
    <JobCreationContext.Provider value={{ jobData, setJobData }}>
      {children}
    </JobCreationContext.Provider>
  );
};

// 自定义hook定义
export const useJobCreation = () => useContext(JobCreationContext);

步骤3:简化调用代码(可选)

修正类型后,无需手动指定prevJobData的类型,TypeScript会自动推导:

// 移除手动指定的类型,代码更简洁
setJobData(prev => ({
  ...prev,
  skillSet: updatedSkillSet,
}));

验证

完成上述修改后,直接传值和函数式更新两种方式都能被TypeScript正确识别,不会再抛出类型错误。

内容的提问来源于stack exchange,提问作者Mike S.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 11:26:31