refactor(web): hasApplicableFix 改类型谓词,消除 applyConflictFix 强转

hasApplicableFix 重写为对象入参类型谓词 patch is ApplicablePatch,谓词命中后 applyConflictFix 里 original/replacement 自动收窄为 string,删两处 as string;补收窄单测。
This commit is contained in:
Yaojia Wang
2026-07-08 13:27:45 +02:00
parent d80d41a08d
commit 9cf4915d49
2 changed files with 45 additions and 19 deletions

View File

@@ -6,15 +6,25 @@ export type FixOutcome =
| { status: "not-found"; text: string } // 有补丁但终稿里找不到原文(作者已改稿/漂移text 原样
| { status: "no-patch"; text: string }; // 该冲突无可自动应用的补丁text 原样
// 已确认可应用的补丁original/replacement 均为 string
export interface ApplicablePatch {
original: string;
replacement: string;
}
// 松散补丁入参original/replacement 可能缺失/为 null审稿可局部修复时才带上
interface LoosePatch {
original: string | null | undefined;
replacement: string | null | undefined;
}
// 是否带可应用补丁original 非空 + replacement 为字符串(容许空串=删除)。
export function hasApplicableFix(
original: string | null | undefined,
replacement: string | null | undefined,
): boolean {
// 类型谓词:命中即把 original/replacement 收窄为 string调用方无需强转。
export function hasApplicableFix(patch: LoosePatch): patch is ApplicablePatch {
return (
typeof original === "string" &&
original.length > 0 &&
typeof replacement === "string"
typeof patch.original === "string" &&
patch.original.length > 0 &&
typeof patch.replacement === "string"
);
}
@@ -25,18 +35,20 @@ export function applyConflictFix(
original: string | null | undefined,
replacement: string | null | undefined,
): FixOutcome {
if (!hasApplicableFix(original, replacement)) {
const patch: LoosePatch = { original, replacement };
if (!hasApplicableFix(patch)) {
return { status: "no-patch", text };
}
// hasApplicableFix 已收窄为 string。
const from = original as string;
const to = replacement as string;
const idx = text.indexOf(from);
// 谓词已把 patch 收窄为 ApplicablePatchoriginal/replacement 皆为 string。
const idx = text.indexOf(patch.original);
if (idx === -1) {
return { status: "not-found", text };
}
return {
status: "applied",
text: text.slice(0, idx) + to + text.slice(idx + from.length),
text:
text.slice(0, idx) +
patch.replacement +
text.slice(idx + patch.original.length),
};
}