eslint-plugin-unicorn prefer-dispose 避坑指南把手写 try/finally 换成 using 显式资源管理【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn你手写的try/finally是不是正在悄悄吞掉原始异常或把两个资源的释放顺序写反eslint-plugin-unicorn 的prefer-dispose用using/await using显式资源管理改写这种手写资源释放顺序自动正确原始异常不再丢。规则在推什么finally最容易翻车的两点恰好是 Explicit Resource Management 的两个优势多个资源按声明的逆序释放LIFOusing保证后打开的先关闭这正是资源依赖的典型清理顺序手写finally写对顺序全靠自觉。原始异常被保留释放本身抛错时标准行为用SuppressedError包装并保留原始错误手写finally里一抛错原异常就静默没了。但这条规则不会改写你所有try/finally——它只盯一种模式资源紧邻try声明且finally的唯一职责就是释放它。先看三组 ❌/✅ 对照最直观的理解方式是看对照。单资源// ❌ const file open(); try { read(file); } finally { file.close(); } // ✅ { using file open(); read(file); }多资源finally必须按声明的逆序释放// ❌ const reader openReader(); const writer openWriter(); try { pipe(reader, writer); } finally { writer.close(); // 后开的先关 reader.close(); } // ✅ { using reader openReader(); using writer openWriter(); pipe(reader, writer); }异步资源// ❌ async function run() { const connection await connect(); try { await query(connection); } finally { await connection.close(); } } // ✅ async function run() { await using connection await connect(); await query(connection); }为什么只给建议、绝不自动改关键在一条安全边界using foo …要求值真正实现Symbol.disposeawait using则是Symbol.asyncDispose——只有.close()的对象不满足直接套using运行时会抛TypeError。没有类型信息就验证不了这一点所以规则hasSuggestions: true只在编辑器里挂一条建议采纳与否由你拍板。判定链四道闸门在 rules/prefer-dispose.js 里你的代码要连过四道闸门才会被报告闸门 1 声明可转变量全作用域只有一处定义是带初始化器的const/letvar、解构、export都不行声明只有一个声明符声明与try同处一个块级作用域。闸门 2 释放可识别finally每条语句都必须是零参数调用方法名在白名单close/dispose/destroy/end内或是foo[Symbol.dispose]()/foo[Symbol.asyncDispose]()的计算写法可选链foo?.close()和await包裹都认同一资源重复释放则整块作废。闸门 3 顺序与复用所有声明必须紧邻且连续地排在try之前finally的释放顺序必须是声明的逆序LIFO否则转换会改变可观察的清理顺序资源在try之后不能被重赋值或再使用using是块级作用域try结束资源已释放。闸门 4 异步上下文只要有一个异步释放await using就必须合法——仅限 async 函数内或模块顶层类静态块里不允许await直接出局。两个附注修复器怎么动手有catch时try { … } catch (…) { … }原样保留只删finally声明被包进新的{块没有catch时try块体被解包进新using块作用域合并。只报错、不给建议finally块内或}与finally之间有注释修复会删掉它们或try块里声明了与资源同名的绑定解包后发生遮蔽此时只报告错误、跳过建议。类型校验别让 .close() 骗了你开启 type-aware linting 后规则会借类型信息确认资源确实实现了Symbol.dispose/Symbol.asyncDispose。两个实现细节值得知道TypeScript 把 well-known symbol 成员存在__dispose9这类转义名下源码直接匹配name.startsWith(__dispose)异步场景再匹配__asyncDispose绕开会引发崩溃的 symbol 转字符串调用一旦类型解析在 TypeScript 深处崩溃已知问题规则保守地当作不可释放——宁可漏报不让 lint 运行挂掉。实际后果只有close()的类 → 不报告const foo: Disposable open()→ 报告联合类型Disposable | {close(): void}混入一个不可释放成员 → 不报告using运行时可能抛错。怎么开启、和谁搭配规则默认关闭recommended: false——源码注释写明等目标升到 Node.js 24原生支持using/await using时再进默认配置。现在要用得自己显式打开flat config 里这样写import unicorn from eslint-plugin-unicorn; export default [ { plugins: {unicorn}, rules: { unicorn/prefer-dispose: error, }, }, ];建议搭配 no-using-resource-escape 一起用prefer-dispose管把try/finally收编进using后者管别让资源从using里跑出去——return资源本身、export它、或返回捕获了它的闭函数都会让作用域退出后拿到已释放的资源。后者在recommended里默认开着。边界速查表场景结果const foo open(); try { … } finally { foo.close(); }✅ 报告多资源finally按声明逆序释放✅ 报告let声明、可选链、dispose/destroy/end、Symbol.dispose✅ 报告async 函数内 / 模块顶层的异步释放✅ 报告带catch建议会保留catch✅ 报告var、解构、无初始化器、export声明❌ 不报foo.close(true)、foo[close]()、if (foo) foo.close()、重复释放❌ 不报finally夹带其他语句、声明没紧邻try❌ 不报资源在try后被复用或重赋值❌ 不报finally按声明顺序非逆序释放❌ 不报非 async 函数 / 类静态块里的异步释放❌ 不报finally内有注释、}与finally间有注释、解包触发同名遮蔽⚠️ 报错但不给建议开类型后类型无Symbol.dispose/asyncDispose❌ 不报三句话定去留声明紧邻try、finally只含零参释放调用、顺序是逆序 → 转资源try之后还要用、需要条件释放、finally兼任其他职责 → 不转TypeScript 项目 → 开 type-aware linting让规则替你确认类型真可释放避开.close()对象的using运行时雷。【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?