升级TypeScript 4.9.3至5.1.3时遇随机类型错误求助
TypeScript 5.1.3升级后Yup校验的类型错误解决
问题背景
将项目从TypeScript 4.9.3升级到5.1.3后,遇到一个诡异的类型错误:
- VS Code和WebStorm都会触发错误,但在文件内做简单编辑(比如敲空格)后,IDE里的错误会暂时消失
- 命令行执行
tsc检查时,错误始终存在 - 本地TSC版本及项目依赖均已更新至5.1.3
相关代码:
const ShortCodeSchema = Yup.object().shape({ code: Yup.string() .min(3) .matches(/^((?!\/).)*$/), languageId: Yup.string().optional(), }); const schema = Yup.object().shape({ title: Yup.string().required("admin.snippets.drawer.validation.name"), shortCodes: Yup.array(ShortCodeSchema).test( "shortcodes", "admin.snippets.drawer.validation.no_deplicate_shortcode", (shortCodes) => { const counts = shortCodes?.reduce((acc, shortCode) => { if (shortCode?.code && acc.has(shortCode.code)) { acc.set(shortCode.code, acc.get(shortCode.code)! + 1); } else if (shortCode?.code) { acc.set(shortCode.code, 1); } return acc; }, new Map<string, number>()); const hasDuplicates = typeof [...(counts ?? []).values()].find((count) => count > 1) === "number"; return !hasDuplicates; } ), });
问题原因
TS 5.x对类型推断的严格性大幅提升,这里核心有两个问题:
- Yup的
test函数参数shortCodes被推断为模糊的联合类型,TS无法确定其具体结构 counts ?? []的写法存在类型不兼容:counts是Map<string, number> | undefined,和数组类型不匹配,TS 5.x会严格拦截这种类型歧义
修复方案
直接修改代码消除类型歧义,优化逻辑:
1. 显式定义类型并约束参数
提前定义ShortCode类型,给test函数的参数指定明确类型,避免TS推断混乱:
type ShortCode = { code?: string; languageId?: string };
2. 处理空值并统一类型
去掉冗余的可选链,先判断shortCodes是否存在;将counts ?? []改为counts ?? new Map(),保证类型统一。
3. 优化重复判断逻辑
用更简洁的some方法替代原有的类型判断写法,同时保证类型安全。
修改后的完整代码:
const ShortCodeSchema = Yup.object().shape({ code: Yup.string() .min(3) .matches(/^((?!\/).)*$/), languageId: Yup.string().optional(), }); type ShortCode = { code?: string; languageId?: string }; const schema = Yup.object().shape({ title: Yup.string().required("admin.snippets.drawer.validation.name"), shortCodes: Yup.array(ShortCodeSchema).test( "shortcodes", "admin.snippets.drawer.validation.no_deplicate_shortcode", (shortCodes: ShortCode[]) => { // 先处理空数组情况 if (!shortCodes) return true; const counts = shortCodes.reduce((acc, shortCode) => { if (shortCode?.code) { acc.set(shortCode.code, (acc.get(shortCode.code) || 0) + 1); } return acc; }, new Map<string, number>()); // 检查是否有重复项 const hasDuplicates = Array.from(counts.values()).some(count => count > 1); return !hasDuplicates; } ), });
内容的提问来源于stack exchange,提问作者lordk
相关产品推荐
相关产品推荐

