修改变量属性时如何为其添加TypeScript类型标注?
解决TypeScript错误:'newExpenses'隐式具有'any'类型
问题根源
你在useMemo的第二个map里直接引用了还未完成初始化的newExpenses,导致TypeScript无法推断其类型,同时形成循环引用,触发7022错误。
修复步骤
1. 定义适配饼图的类型接口
先在文件顶部定义新类型,明确饼图所需字段:
import { Category } from "@/types"; // 新增:适配饼图的类型 type PieChartCategory = { id: string; name: string; value: number; color: string; };
2. 重构useMemo逻辑,消除循环引用
把计算最大value的逻辑从第二个map中抽离,先处理排序后的中间数组,再基于该数组计算颜色,避免直接引用未初始化的newExpenses:
const newExpenses = useMemo<PieChartCategory[]>(() => { // 第一步:计算每个分类的总支出并排序 const sortedCategories = categories .map((category) => ({ id: category.name, name: category.name, value: Number( category.expenses .reduce((previous, current) => previous + current.price, 0) .toFixed(2) ), })) .sort((a, b) => a.value - b.value); // 第二步:计算最大value的位数,用于透明度计算 const maxValue = sortedCategories[sortedCategories.length - 1]?.value || 0; const maxDigitLength = maxValue.toString().length; // 第三步:添加color属性 return sortedCategories.map((category) => ({ ...category, color: `rgba(64,224,208,${category.value / Math.pow(10, maxDigitLength)})`, })); }, [categories]);
3. 给newExpenses添加类型注解
通过useMemo<PieChartCategory[]>明确返回值类型,让TypeScript完全知晓变量的类型结构。
完整修复后的核心代码片段
import DashboardBox from "@/components/DashboardBox"; import { useGetExpensesQuery, useGetCategoriesQuery } from "@/state/api"; import { useMemo } from "react"; import { Cell, Pie, PieChart, ResponsiveContainer, Tooltip } from "recharts"; import { Category } from "@/types"; type Props = {}; // 新增适配类型 type PieChartCategory = { id: string; name: string; value: number; color: string; }; const Row1 = (props: Props) => { const { data: categories, isLoading } = useGetCategoriesQuery(); if (!categories || isLoading) { return <p>Loading...</p>; } const newExpenses = useMemo<PieChartCategory[]>(() => { const sortedCategories = categories .map((category) => ({ id: category.name, name: category.name, value: Number( category.expenses .reduce((previous, current) => previous + current.price, 0) .toFixed(2) ), })) .sort((a, b) => a.value - b.value); const maxValue = sortedCategories[sortedCategories.length - 1]?.value || 0; const maxDigitLength = maxValue.toString().length; return sortedCategories.map((category) => ({ ...category, color: `rgba(64,224,208,${category.value / Math.pow(10, maxDigitLength)})`, })); }, [categories]); return ( <> <DashboardBox gridArea="a"> <ResponsiveContainer width="100%" height="100%"> <PieChart width={400} height={400}> <Pie isAnimationActive={true} paddingAngle={5} innerRadius={60} outerRadius={80} label data={newExpenses} dataKey="value" cx="50%" cy="50%" fill="#12efc8" > {newExpenses.map((entry, index) => ( <Cell key={`cell-${index}`} fill={entry.color} /> ))} </Pie> <Tooltip /> </PieChart> </ResponsiveContainer> </DashboardBox> </> ); }; export default Row1;
额外说明
- 重构后消除了循环引用,TypeScript可正确推断类型
- 明确的类型注解提升了代码可读性与可维护性
- 抽离中间变量让逻辑更清晰,便于后续调整
内容的提问来源于stack exchange,提问作者Mathew
相关产品推荐
相关产品推荐

