React+TypeScript中merge函数报TypeError: left is undefined的解决咨询
修复归并排序中
TypeError: left is undefined及类型错误问题 问题描述
在React+TypeScript项目中实现归并排序时,触发merge函数会报错TypeError: left is undefined。为了避免left.shift()和right.shift()的语法错误,暂时将这两个参数设为any类型,需要修复这些问题让函数正常运行。
问题根源
- mergeSort返回值异常:原代码用
for循环套setTimeout执行递归逻辑,但setTimeout是异步的,mergeSort函数没有返回有效数组,导致传给merge的left和right都是undefined。 - 数组操作错误:使用
splice修改原数组,不仅破坏React state的不可变性,还会导致递归过程中数组被意外修改。 - 类型不匹配:因为
mergeSort返回undefined,把merge参数设为number[]时会出现类型错误,本质是逻辑错误导致的类型问题。
修复方案
以下是修正后的完整代码,关键改动标注如下:
import { useEffect, useContext } from "react"; import { arrContext } from "../arr-context-provider"; import Visualizer from "../visualizer"; const MergeSort: React.FC = () => { const [arr, setArr] = useContext<[number[], React.Dispatch<React.SetStateAction<number[]>>]>(arrContext); // 封装延迟函数,用于可视化步骤的间隔 const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); useEffect(() => { // 初始数组为空时不执行 if (arr.length === 0) return; // 拷贝初始数组,避免修改原state const initialArr = [...arr]; mergeSort(initialArr); }, [arr]); const mergeSort = async (currentArr: number[]): Promise<number[]> => { // 递归终止条件:数组长度小于2直接返回 if (currentArr.length < 2) { return currentArr; } const mid = Math.floor(currentArr.length / 2); // 用slice拆分数组,不修改原数组 const left = currentArr.slice(0, mid); const right = currentArr.slice(mid); // 递归排序左右子数组 const sortedLeft = await mergeSort(left); const sortedRight = await mergeSort(right); // 合并后更新state,并添加延迟 const mergedArr = await merge(sortedLeft, sortedRight); await delay(100); return mergedArr; }; const merge = (left: number[], right: number[]): Promise<number[]> => { return new Promise(resolve => { const merged: number[] = []; // 拷贝数组避免修改原排序后的数组 const leftCopy = [...left]; const rightCopy = [...right]; while (leftCopy.length && rightCopy.length) { if (leftCopy[0] < rightCopy[0]) { merged.push(leftCopy.shift()!); } else { merged.push(rightCopy.shift()!); } } const finalMerged = [...merged, ...leftCopy, ...rightCopy]; // 更新state为合并后的数组 setArr(finalMerged); resolve(finalMerged); }); }; return <Visualizer />; }; export default MergeSort;
关键改动说明
- 异步递归处理:把
mergeSort改成异步函数,用await处理递归和延迟,确保每次排序步骤完成后再执行合并,同时保证函数返回正确的number[]。 - 数组不可变性:用
slice拆分数组,拷贝数组进行操作,避免修改原数组和React state,符合React的状态管理规范。 - 类型修正:
merge的参数明确设为number[],因为mergeSort现在返回有效的数组,类型匹配后shift()的语法错误也会消失(用!断言shift()不会返回undefined,因为已经判断了数组长度大于0)。 - useEffect优化:添加
arr作为依赖,确保数组变化时重新执行排序,同时拷贝初始数组避免直接操作state。
内容的提问来源于stack exchange,提问作者bascott
相关产品推荐
相关产品推荐

