如何解决TypeScript中数组‘可能为undefined’的报错问题
问题描述
我通过API调用获取数据后,将其赋值给availableOfferings数组:
const { offerings: availableOfferings } = useGetOfferings();
之后定义了两个依赖该数组的变量:
const bestOffering = availableOfferings[0]; const relevantOfferings = availableOfferings .slice(1) .filter((off: any) => isGoodFit(off));
初始化时遇到TypeScript错误:'availableOfferings' is possibly 'undefined'。
我尝试了以下方案,虽然可行但不够优雅:
const bestOffering = availableOfferings ? availableOfferings[0] : undefined; const relevantOfferings = availableOfferings ? availableOfferings.slice(1).filter((off: any) => isGoodFit(off)) : undefined;
以下是useGetOfferings的实现代码:
export const OfferingsContext = createContext<{ [x: string]: any; offerings?: { [x: string]: any; }; }>({ offerings: {}, }); export function useGetOfferings() { return useContext(OfferingsContext); }
function OfferingsProvider({ children }: Props) { const [offerings, setOfferings] = useState([]); const [hasGoodFits, setHasGoodFits] = useState(undefined); const { getAccessTokenSilently } = useAuth0(); const fetchData = async () => { try { const responseOfferings = await BusinessApi.getOfferings( getAccessTokenSilently ); const hasGoodFitsResult = responseOfferings.data.data.some( (offering: any) => isGoodFit(offering) ); setOfferings(responseOfferings.data.data); setHasGoodFits(hasGoodFitsResult); return { responseOfferings, hasGoodFitsResult }; } catch (error) { console.log(error); } }; useEffect(() => { fetchData(); }, []); return ( <OfferingsContext.Provider value={{ offerings, fetchData, hasGoodFits }} children={children} /> ); }
请问解决该问题的最优方案是什么?
最优解决方案
1. 修正Context类型定义(核心优化)
当前Context的类型存在两处关键问题:
offerings被标记为可选对象类型,但实际Provider中它是数组结构- 初始值设为
{},和Provider中useState([])的数组类型冲突
修正后的类型定义(建议补充具体的Offering类型,替换any提升安全性):
// 定义Offering的具体类型,根据业务字段补充 type Offering = { id?: string; name?: string; [key: string]: any; }; export const OfferingsContext = createContext<{ offerings: Offering[]; fetchData: () => Promise<{ responseOfferings?: any; hasGoodFitsResult?: boolean }>; hasGoodFits: boolean | undefined; }>({ offerings: [], // 初始值设为空数组,和Provider状态保持一致 fetchData: async () => ({}), hasGoodFits: undefined, });
2. 简化变量赋值逻辑
修正类型后,availableOfferings不再可能是undefined,直接操作数组即可:
const { offerings: availableOfferings } = useGetOfferings(); // 空数组时返回undefined,符合业务逻辑 const bestOffering = availableOfferings[0]; // 空数组slice(1)后仍是空数组,filter后结果也为空,无需额外判断 const relevantOfferings = availableOfferings .slice(1) .filter((off: Offering) => isGoodFit(off));
如果暂时不想修改Context类型,也可以用可选链+空值合并运算符简化原有代码:
const bestOffering = availableOfferings?.[0]; // 确保relevantOfferings始终是数组类型,避免后续使用时出现undefined const relevantOfferings = availableOfferings?.slice(1).filter((off: any) => isGoodFit(off)) ?? [];
3. 可选:添加加载状态增强用户体验
如果需要在数据加载完成前做UI提示,可以在Provider中补充加载状态:
function OfferingsProvider({ children }: Props) { const [offerings, setOfferings] = useState<Offering[]>([]); const [hasGoodFits, setHasGoodFits] = useState<boolean | undefined>(undefined); const [isLoading, setIsLoading] = useState(true); // 新增加载状态 const { getAccessTokenSilently } = useAuth0(); const fetchData = async () => { try { setIsLoading(true); const responseOfferings = await BusinessApi.getOfferings(getAccessTokenSilently); const hasGoodFitsResult = responseOfferings.data.data.some((offering: Offering) => isGoodFit(offering)); setOfferings(responseOfferings.data.data); setHasGoodFits(hasGoodFitsResult); return { responseOfferings, hasGoodFitsResult }; } catch (error) { console.log(error); } finally { setIsLoading(false); // 请求完成后关闭加载状态 } }; useEffect(() => { fetchData(); }, []); return ( <OfferingsContext.Provider value={{ offerings, fetchData, hasGoodFits, isLoading }} children={children} /> ); }
在组件中根据加载状态处理UI:
const { offerings: availableOfferings, isLoading } = useGetOfferings(); if (isLoading) { return <div>加载中...</div>; } const bestOffering = availableOfferings[0]; const relevantOfferings = availableOfferings.slice(1).filter(isGoodFit);
内容的提问来源于stack exchange,提问作者Jevon Cochran
相关产品推荐
相关产品推荐

