React中为异步获取JSON的箭头函数加类型标注遇错求助
修复TypeScript嵌套JSON类型标注与状态赋值错误
问题背景
我尝试为一个获取JSON文件的异步函数添加TypeScript类型标注,JSON返回多层嵌套结构,不想逐个定义嵌套对象类型,于是声明了如下类型:
type Dictionary = { menu: Record<string, unknown>; pages: Record<string, unknown>; result: Record<string, unknown>; };
对应的函数实现如下:
const getData = async (lang: string): Promise<Dictionary> => { const path = `src/assets/file${lang}.json`; try { const response = await fetch(path); if (!response.ok) { throw new Error(`Some error`); } const data = await response.json(); setDict(data.menu); } catch (error) { if (error) setError(error); } }; useEffect(() => { getData(lang); }, []);
运行后出现以下类型错误:
- Unsafe assignment of an
anyvalue. - Unsafe argument of type
anyassigned to a parameter of typeSetStateAction<null> - Unsafe member access .menu on an
anyvalue. - Argument of type '{}' is not assignable to parameter of type 'SetStateAction'.
- Type '{}' provides no match for the signature '(prevState: null): null'.
错误原因解析
response.json()类型缺失:该方法默认返回any类型,TypeScript无法识别data结构,导致访问data.menu和赋值给setDict时触发类型不安全提示。- 函数返回值与声明不匹配:
getData声明返回Promise<Dictionary>,但内部无return语句,违反类型约定。 - 状态类型不兼容:
setDict对应的状态初始值为null,但未将Record<string, unknown>纳入状态类型,无法接收data.menu的值。 - 错误处理类型问题:
catch块中的error是unknown类型,直接赋值给setError会触发类型不兼容错误。
修复步骤
1. 为解析后的JSON添加类型断言
明确告知TypeScript解析后的JSON符合Dictionary类型,消除any类型带来的不安全提示:
const data = await response.json() as Dictionary;
2. 修正函数返回类型
如果函数不需要返回数据,将返回类型改为Promise<void>,避免类型声明与实际行为不符:
const getData = async (lang: string): Promise<void> => { // 原有逻辑 };
3. 对齐状态变量类型
修改setDict对应的useState声明,让状态类型包含Record<string, unknown>和null:
const [dict, setDict] = useState<Record<string, unknown> | null>(null);
4. 规范错误处理类型
先判断error的实际类型,再赋值给setError,同时给错误状态指定正确类型:
// 声明错误状态 const [error, setError] = useState<Error | null>(null); // 在catch块中处理 catch (err) { if (err instanceof Error) { setError(err); } else { setError(new Error(String(err))); } }
5. 补充useEffect依赖项
将lang添加到useEffect的依赖数组中,避免React的依赖缺失警告:
useEffect(() => { getData(lang); }, [lang]);
完整修复代码
import { useEffect, useState } from 'react'; type Dictionary = { menu: Record<string, unknown>; pages: Record<string, unknown>; result: Record<string, unknown>; }; const YourComponent = ({ lang }: { lang: string }) => { const [dict, setDict] = useState<Record<string, unknown> | null>(null); const [error, setError] = useState<Error | null>(null); const getData = async (lang: string): Promise<void> => { const path = `src/assets/file${lang}.json`; try { const response = await fetch(path); if (!response.ok) { throw new Error(`请求失败,状态码:${response.status}`); } const data = await response.json() as Dictionary; setDict(data.menu); } catch (err) { if (err instanceof Error) { setError(err); } else { setError(new Error('未知错误')); } } }; useEffect(() => { getData(lang); }, [lang]); return ( <div> {error && <p>错误提示:{error.message}</p>} {/* 组件其他内容 */} </div> ); }; export default YourComponent;
内容的提问来源于stack exchange,提问作者Jhon
相关产品推荐
相关产品推荐

