/** * Store action 统一错误处理工具(任务 #7 DRY 抽离)。 * * 之前 4 个 store(knowledge/ideas/projects/tasks)共 38 处重复: * try { ... } catch (e: any) { state.error = e?.toString() ?? t('xxx') } * * 本工具: * - 用 `catch (e: unknown)` 替代 `any`(类型安全) * - 失败时写 state.error,返回 undefined(调用方判断) * - 成功时返回 fn 结果 * * 注:带 seq 竞态守卫的场景调用方需在 fn 内部判断,不在本工具职责范围。 */ // (Ref import 已移除,_Unused 类型已删除) /** 带 error 字段的 store state 形状(仅约束 error,其他字段任意)。仅本模块内部使用。 */ interface ErrorSink { error: string | null } /** * 执行异步 action,失败时写 state.error + 返回 undefined。 * * @param state 带 error 字段的响应式 state * @param i18nKey 失败时的 i18n 文案 key(兜底) * @param fn 异步 action * @returns 成功返 fn 结果;失败返 undefined */ export async function runWithCatch( state: ErrorSink, i18nKey: string, fn: () => Promise, ): Promise { try { return await fn() } catch (e: unknown) { state.error = stringifyError(e) ?? i18nKey return undefined } } // stringifyError 仅本模块内部使用(runWithCatch/runWithCatchGuarded 调用),不导出。 function stringifyError(e: unknown): string | undefined { if (typeof e === 'string') return e if (e instanceof Error) return e.message || e.toString() if (e && typeof e === 'object' && 'toString' in e) { try { return String((e as { toString(): string }).toString()) } catch { return undefined } } return undefined } /** * Variant:带前置守卫的错误捕获。 * * 用于「旧请求的失败不污染当前视图」场景(如 seq 守卫)。 * * @param guard 返回 true 时才写 state.error;false 时静默(旧响应丢弃) */ export async function runWithCatchGuarded( state: ErrorSink, i18nKey: string, guard: () => boolean, fn: () => Promise, ): Promise { try { return await fn() } catch (e: unknown) { if (guard()) { state.error = stringifyError(e) ?? i18nKey } return undefined } } // _Unused 类型从未被外部 import,已删除(同时移除上方 Ref import)。