GitHub Desktop 的 TypeScript 代码风格指南:命名约定、JSDoc、Dispatcher 可见性与异步 API 实践
开发工具桌面应用【免费下载链接】desktopFork of GitHub Desktop to support various Linux distributions项目地址https://gitcode.com/gh_mirrors/des/desktop点击查看免费下载本指南以 GitHub Desktop 仓库本仓库为其面向多种 Linux 发行版的 Fork的官方贡献文档 docs/contributing/styleguide.md 为骨架结合仓库内实际生效的 ESLint 配置、AppStore 源码与工具脚本系统梳理该项目在 TypeScript 开发中的命名规范、代码注释格式、状态变更入口约定以及异步/同步 API 的使用边界。读完本文你将能够按该仓库的工程标准编写新代码并理解这些约定在AppStore、Dispatcher等核心模块中的落地方式。一、基础命名规范camelCase 与 PascalCase文档开篇给出的 Do 清单只有三条却是整个代码库可读性的根基方法method使用 camelCase如getSelectedState、updateRepository与 JavaScript 社区惯例一致类名class使用 PascalCase如AppStore、Dispatcher、Repository在编辑器中启用 ESLint让机器强制执行而非依赖人工审查。这些约定并非停留在文档层面仓库根目录的 .eslintrc.yml 通过typescript-eslint/naming-convention规则将其固化为error级别的强制检查关键配置如下typescript-eslint/naming-convention: - error - selector: interface format: - PascalCase custom: regex: ^I[A-Z] match: true - selector: class format: - PascalCase - selector: variableLike format: null custom: # 禁止把内置类型名用作变量名 regex: ^(any|Number|number|String|string|Boolean|boolean|Undefined|undefined)$ match: false几点值得注意的细节接口命名除要求 PascalCase 外还强制接口名以大写I开头正则^I[A-Z]例如IAPIRepoRuleset、IAPIAccount这类命名在 app/src/lib/api.ts 中大量出现变量名禁止使用any、Number、String、Boolean、undefined等类型关键字作为变量名这是从旧版 TSLint 的variable-name规则继承下来的约束.eslintrc.yml类型断言风格typescript-eslint/consistent-type-assertions强制使用as语法而非尖括号断言Typevalue避免与 JSX 语法产生歧义成员声明顺序typescript-eslint/member-ordering规定类成员按static-field → static-method → field → abstract-method → constructor → method的顺序排列让类结构在阅读时更具可预测性。二、在编辑器与 CI 中启用 ESLint为了让上述规则真正生效仓库同时配套了运行脚本与自定义规则集。在 package.json 中可以找到以下命令lint:src: yarn eslint-check yarn eslint, lint:src:fix: yarn eslint --fix, eslint: eslint --cache --rulesdir ./eslint-rules \./eslint-rules/**/*.js\ \./script/**/*.ts{,x}\ \./app/{src,typings,test}/**/*.{j,t}s{,x}\ \./changelog.json\, eslint-check: eslint --print-config .eslintrc.* | eslint-config-prettier-check三个要点自定义规则目录--rulesdir ./eslint-rules将仓库自研的 ESLint 规则注入检查包括insecure-random、react-no-unbound-dispatcher-props、react-readonly-props-and-state、react-proper-lifecycle-methods、no-loosely-typed-webcontents-ipc这些规则在 .eslintrc.yml 中全部声明为error其实现与配套测试位于 eslint-rules 目录如 eslint-rules/insecure-random.jsPrettier 兼容.eslintrc.yml通过extends引入prettier、prettier/react、prettier/typescript-eslint并依赖eslint-plugin-prettier、eslint-config-prettier保证风格规则与格式化工具不冲突分层配置根配置之外测试与脚本目录还有独立覆盖。例如 app/test/.eslintrc.yml 关闭了no-unused-expressions因 Chai 断言风格会触发该规则与strictscript/.eslintrc.yml 则对unicorn/no-process-exit、import/no-commonjs放行。此外根配置里还有两条颇有项目特色的内置规则no-restricted-imports禁止直接import { ipcRenderer } from electron或import { ipcMain } from electron要求改用仓库封装的ipc-renderer/ipc-main模块以获得强类型 IPC 方法.eslintrc.ymlno-restricted-syntax禁止默认导出ExportDefaultDeclaration即全仓库统一使用命名导出。三、用 JSDoc 记录代码/**开头的注释约定项目选择JSDoc作为统一的文档格式理由是 TypeScript 编译器原生支持解析 JSDoc 并在 IDE 中呈现同时 JSDoc 中的可见性、继承、成员归属等元数据与 TypeScript 类型系统本身高度重合。当前仓库尚未生成独立的文档站点也不强制校验格式但注释风格已在文档中明确规范。最基础的形式是单行注释关键在于/**开头必须恰好是两个星号这是合法的 JSDoc 起始标记/** This is a documentation string */需要多行描述时遵循类似 git commit message 的写法先用一行短标题概括主题空一行后再展开细节/** * This is a title, keep it short and sweet * * Go nuts with documentation here and in more paragraphs if you need to. */ESLint 侧也同步启用了eslint-plugin-jsdoc的系列规则.eslintrc.ymljsdoc/check-alignment对齐、jsdoc/check-tag-names标签名合法性、jsdoc/check-types、jsdoc/implements-on-classes、jsdoc/tag-lines、jsdoc/no-undefined-types、jsdoc/valid-types。文档同时坦诚标注jsdoc/require-jsdoc与jsdoc/check-param-names这类强制规则目前处于关闭状态属于将来希望逐步偿还的 技术债。四、AppStore 方法可见性Dispatcher 模式与下划线前缀这是本指南最具项目特色的约定直接服务于架构分层。在 GitHub Desktop 中Dispatcher是绝大多数会改变应用状态的交互入口实际工作随后被委托给AppStore。为避免调用方绕过 Dispatcher 直接操作 AppStore 内部方法项目采用让方法看起来不好惹的双重手段方法名加下划线前缀_在 JSDoc 注释中明确提示调用方应改走Dispatcher。文档给出的示例方法/** This shouldnt be called directly. See Dispatcher. */ public async _repositoryWithRefreshedGitHubRepository(repository: Repository): PromiseRepository { // ... }这一约定在 app/src/lib/stores/app-store.ts 中有数十处真实落地。例如/** This shouldnt be called directly. See Dispatcher. */ public _updateCachedRepoRulesets(rulesets: ArrayIAPIRepoRuleset | null) { for (const rs of rulesets) { if (rs ! null) { this.cachedRepoRulesets.set(rs.id, rs) } } }以及 app/src/lib/stores/app-store.ts 中的/** This shouldnt be called directly. See Dispatcher. */ public _changeCommitSelection( repository: Repository, shas: ReadonlyArraystring, isContiguous: boolean ): void {对应的 Dispatcher 实现位于 app/src/ui/dispatcher/dispatcher.ts。文档中 Dispatcher 与 AppStore 的原始链接分别指向app/src/lib/dispatcher/dispatcher.ts与app/src/lib/stores/app-store.ts从当前仓库源码结构看Dispatcher 实际位于app/src/ui/dispatcher/目录下读者可据此定位。配套的 ESLint 自定义规则react-no-unbound-dispatcher-props见 eslint-rules/react-no-unbound-dispatcher-props.js进一步约束 React 组件中 dispatcher 属性的使用方式从工具层面防止误用。这套约定的本质是通过命名 注释的软约束引导调用方走向正确的架构路径UI 组件只与 Dispatcher 打交道状态变更逻辑收敛在 AppStore 内从而保持数据流单向、可控。五、异步与同步 Node API 的取舍项目对 Node 核心 API 的使用有一套明确的二分策略并用 ESLint 的no-sync规则在 .eslintrc.yml 中配置为error强制落地。应用代码Application Code默认异步应用运行期代码应优先使用异步核心 API如fs.promises系列、readFile/writeFile除非存在令人信服的理由且没有异步替代方案确需使用同步 API 时方法名必须带Sync后缀向调用方明示其阻塞行为测试代码可以退回到Sync方法以换取可读性与简洁性。脚本Scripts默认同步构建、发布等一次性脚本中异步带来的收益并不明显反而同步 API 让代码更易阅读因此脚本侧放宽限制。仓库源码中可以找到这两种场景的真实佐证应用代码中少数用到同步 API 的地方均集中在启动期与崩溃兜底路径例如 app/src/lib/get-title-bar-config.ts 使用existsSync/readFileSync读取标题栏配置app/src/lib/source-map-support.ts 使用Fs.existsSync/Fs.readFileSync加载 source map——这些都属于启动阶段一次性读取、无异步替代收益的合理例外且方法本身通过工具链被严格审查。六、写在最后约定的协作价值综合来看这份风格指南的篇幅不长但每一节都对应仓库中可验证的工程实践命名约定由naming-convention强制执行JSDoc 有eslint-plugin-jsdoc护航AppStore 可见性约定在 app/src/lib/stores/app-store.ts 中有几十处实例异步/同步边界由no-sync与命名后缀共同约束。对贡献者而言遵循本指南意味着提交的代码能无缝通过 package.json 中的yarn lint:src检查并天然契合项目的分层架构对阅读者而言这些约定让哪些方法可以直接调用、哪些应该通过 Dispatcher 间接触发变得一目了然。如果你正准备向本仓库提交代码建议按本文顺序自检命名是否符合 camelCase/PascalCase 与接口I前缀、注释是否使用/**JSDoc 格式、是否误调用了带_前缀的 AppStore 方法、应用代码中是否引入了不必要的同步 API——完成这四步你的改动就与仓库既有代码风格保持了一致。赞分享开发工具桌面应用【免费下载链接】desktopFork of GitHub Desktop to support various Linux distributions项目地址https://gitcode.com/gh_mirrors/des/desktop点击查看免费下载相关推荐为什么你需要OSlash10个Python函数式编程的实用场景为什么你需要OSlash10个Python函数式编程的实用场景 如果你正在学习Python函数式编程或者想要在项目中应用更优雅的错误处理、状态管理和异步流程Spotube代码规范代码风格与命名约定Spotube代码规范代码风格与命名约定 Spotube作为一个跨平台的开源音乐客户端采用了清晰的代码规范来确保项目的可维护性和一致性。本文将详细介绍项目的音视频跨平台FunClip终极指南免费开源AI视频智能剪辑工具完整教程FunClip终极指南免费开源AI视频智能剪辑工具完整教程 想象一下一小时的会议录像你只想留下某位发言人的三句话一整节网课你只想要讲重点的20秒。传统音视频语音人工智能AI 应用本地部署上一篇终极指南如何在Windows家庭版上免费启用远程桌面多用户会话下一篇解锁Windows远程桌面功能RDP Wrapper Library完全指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考