React Context中声明接口后出现TS错误:类型不存在指定属性?
我正在开发一个需要跨组件管理状态的React应用,采用React Context结合TypeScript实现,但遇到了类型错误。需求是点击按钮时将本地错误同步到全局状态,在LocalErrors组件中验证表单并更新错误,但现在抛出TS2339错误:Property 'LocalName' does not exist on type 'ErrProvider[]'——明明已经在ErrProvider接口中定义了LocalName属性,想知道问题原因及解决方法。
相关代码
主组件中的接口定义
interface ErrProvider { LocalName?: string, } interface formContextType { LocalErrValue: { localErr: Array<any>, setLocalErr: Dispatch<SetStateAction<Array<any>>> } errValue: { errors: Array<ErrProvider>, setErrors: Dispatch<SetStateAction<Array<ErrProvider>>> } }
Context初始化代码
export const formContext = createContext<formContextType>({ errValue: { errors: [], setErrors: () => {} }, LocalErrValue: { localErr: [], setLocalErr: () => {} }, });
App组件代码
export const MyApp = () => { const [localErr, setLocalErr] = useState(Array<any>); const LocalErrValue = {localErr, setLocalErr} const [errors, setErrors] = useState(Array<ErrProvider>); const errValue = {errors, setErrors} function submitCheck(): void { setErrors(localErr) } return ( <formContext.Provider value={{ifaErrValue, errValue}}> <LocalErrors/> <button onClick={submitForm} > <p>Make Reservation</p> </button> </formContext.Provider> ) };
LocalErrors组件代码
interface LocalFormFields { LocalName?: string } export const LocalErrors = () => { const {LocalErrValue, errValue} = useContext(formContext); const {localErr, setLocaErr} = ifaErrValue const {errors, setErrors} = errValue const [localForm, setLocalForm] = useState<IFAFormFields>({}); function setField(field: string, value: string | number) { setlocalForm({ ...localForm, [field]: value, }); } function validateForm(): any { const newErrors: any = {}; if (!localForm.AdvisorName || loccalForm.AdvisorName === "") newErrors.AdvisorName = `Please enter first name`; return newErrors; } useEffect(() => { setLocalErr(validateForm()) }, [localForm]); return <div> <Form.Group controlId="formBasicEmail" > <Form.Control type="name" placeholder="Local Name" onChange={(e) => setField(" LocalName", e.target.value) } /> </Form.Group> <p> {errors.LocalName} </p> </div> }
错误信息
TS2339: Property 'LocalName' does not exist on type 'ErrProvider[]'.
问题原因与解决方法
1. 核心错误原因
你在formContextType中定义errValue.errors为Array<ErrProvider>类型(即ErrProvider对象的数组),但在LocalErrors组件中直接用errors.LocalName访问数组的属性——数组本身没有LocalName属性,只有数组内的单个ErrProvider对象才具备该属性,这就是报错的根本原因。
2. 全量修正方案
除核心错误外,代码中还有拼写、类型初始化、数据结构不匹配等问题,以下是完整修正步骤:
(1)修正状态初始化方式
useState需要传入初始值而非类型本身:
// 错误写法 const [localErr, setLocalErr] = useState(Array<any>); const [errors, setErrors] = useState(Array<ErrProvider>); // 修正后 const [localErr, setLocalErr] = useState<any[]>([]); const [errors, setErrors] = useState<ErrProvider[]>([]);
(2)修正Context Provider的值拼写错误
App组件中Provider的value误写为ifaErrValue,实际应是LocalErrValue:
// 错误写法 <formContext.Provider value={{ifaErrValue, errValue}}> // 修正后 <formContext.Provider value={{LocalErrValue, errValue}}>
(3)修正LocalErrors组件的拼写错误
setLocaErr→setLocalErrifaErrValue→LocalErrValuesetlocalForm→setLocalFormloccalForm→localFormIFAFormFields→LocalFormFields(与接口定义保持一致)setField(" LocalName", ...)去掉空格,改为"LocalName"(避免字段名带空格)
(4)调整错误数据结构匹配需求
当前validateForm返回的是对象,但LocalErrValue.localErr和全局errors定义为数组,类型不兼容。结合表单错误的存储逻辑,建议将类型调整为对象:
// 修正主组件接口 interface ErrProvider { LocalName?: string, // 可添加其他表单错误字段 } interface formContextType { LocalErrValue: { localErr: ErrProvider, setLocalErr: Dispatch<SetStateAction<ErrProvider>> } errValue: { errors: ErrProvider, setErrors: Dispatch<SetStateAction<ErrProvider>> } } // 修正Context初始化 export const formContext = createContext<formContextType>({ errValue: { errors: {}, setErrors: () => {} }, LocalErrValue: { localErr: {}, setLocalErr: () => {} }, }); // 修正App组件状态初始化 const [localErr, setLocalErr] = useState<ErrProvider>({}); const [errors, setErrors] = useState<ErrProvider>({}); // 修正LocalErrors组件的validateForm返回类型 function validateForm(): ErrProvider { const newErrors: ErrProvider = {}; if (!localForm.LocalName || localForm.LocalName === "") newErrors.LocalName = `Please enter local name`; return newErrors; }
(5)修正错误访问方式
调整类型后,全局错误errors为ErrProvider对象,可正常访问errors.LocalName:
<p>{errors.LocalName}</p>
(6)修正submitCheck的类型兼容
调整类型后,submitCheck中的setErrors(localErr)不再有类型错误,两者均为ErrProvider类型。
内容的提问来源于stack exchange,提问作者Kevin

