资讯动态

TypeScript 风格指南与编码约定:一份基于 typescript-book 仓库的可执行命名与格式规范

发布时间:2026/9/20 13:00:30 来源:尧图企业网站定制
教程【免费下载链接】typescript-book:books: The definitive guide to TypeScript and possibly the best TypeScript book :book:. Free and Open Source 项目地址https://gitcode.com/gh_mirrors/ty/typescript-book点击查看免费下载本文是一份非官方的 TypeScript Style Guide源自 typescript-book 仓库的 docs/styleguide/styleguide.md 章节。它并非强制教条而是团队在命名、格式与 API 设计上产生分歧时用来一锤定音的参考基线。读完本文你将掌握变量/类/接口/命名空间/枚举的命名规范、null与undefined的取舍策略、引号与缩进等格式约定以及type与interface的选择依据并能结合本仓库的编译示例sample.ts与编译产物sample.js理解每条规则背后的真实代码形态。说明风格指南的定位是打破平局tiebreaker。作者在原文中明确表示个人不会在团队中强制执行这些约定但在有人追求强一致性时这些规则可以作为裁决依据。真正更值得关注的是 tips 章节 中那些作者更为坚持的观点例如 type assertion 是糟糕的、property setters 是糟糕的等。变量与函数统一使用camelCase变量名与函数名统一使用camelCase理由是这符合 JavaScript 的惯例。Badvar FooVar; function BarFunc() { }Goodvar fooVar; function barFunc() { }注意这里的示例保留了var关键字是原文档沿用的历史写法。在现代 TypeScript 项目中声明变量更推荐使用let与const参见 let 与 const 章节但命名约定本身不受影响——camelCase适用于所有声明形式。类类名PascalCase成员与方法camelCase类名使用PascalCase这同样是标准 JavaScript 中的惯例。Badclass foo { }Goodclass Foo { }类的成员与方法使用camelCase这自然延续了变量与函数的命名约定Badclass Foo { Bar: number; Baz() { } }Goodclass Foo { bar: number; baz() { } }本仓库的 docs/styleguide/sample.ts 就是这一规则的直接写照——它定义了一个符合规范的类Foo成员bar与方法baz均为camelCasenamespace asdfasdf { class Foo { bar: number; baz() { } } }查看其编译产物 docs/styleguide/sample.js 可以直观看到 TS 编译器的输出形态baz被编译为原型方法Foo.prototype.baz function () { };类名保持Foo不变。这一对照示例说明命名规范不仅作用于源码层面也会原样反映在编译产物中——保持类名PascalCase、方法名camelCase能让生成代码与手写代码保持一致的阅读体验。接口PascalCase名称、camelCase成员不要加I前缀接口的命名规则与类类似名称用PascalCase成员用camelCase。不要为接口添加I前缀。理由是这种匈牙利命名法并不符合主流惯例TypeScript 自带的lib.d.ts中定义的重要接口都没有I前缀例如Window、Document等。关于lib.d.ts中这些无前缀全局接口的详细构成可参考 lib.d.ts 章节。Badinterface IFoo { }Goodinterface Foo { }类型别名PascalCase名称、camelCase成员type别名类型别名的命名同样遵循PascalCase成员使用camelCase理由与类一致。例如type Foo { bar: number; baz: () void; };类型别名的详细用法联合类型、交叉类型、字面量类型等见 类型系统相关章节。命名空间使用PascalCase命名空间使用PascalCase这是 TypeScript 团队自身遵循的惯例。原因很直接命名空间本质上就是带静态成员的类类名既然用PascalCase命名空间名也应如此。Badnamespace foo { }Goodnamespace Foo { }本仓库的 docs/styleguide/sample.ts 展示了命名空间的真实用法namespace formatting、namespace asdfasdf其编译产物 docs/styleguide/sample.js 则揭示了命名空间的底层实现——它被编译为经典的 IIFE 模块模式use strict; var formatting; (function (formatting) { var FooVar; function BarFunc() { } })(formatting || (formatting {}));从这段编译产物可以确认命名空间在运行时就是一个普通对象内部的变量/函数挂载其上与带静态成员的类在语义上确实高度等价这正是PascalCase命名依据的代码级印证。命名空间与现代模块ES Modules的取舍关系可参考 命名空间章节 与 模块章节。枚举枚举名与成员均使用PascalCase枚举名使用PascalCase理由是枚举是一种类型与类的命名一致。Badenum color { }Goodenum Color { }枚举成员同样使用PascalCase。这是 TypeScript 团队即语言创造者遵循的惯例例如编译器内部的SyntaxKind.StringLiteral这类成员命名。同时PascalCase的成员命名也有助于把其他语言例如 C#、Java的代码翻译到 TypeScript 时保持一致。Badenum Color { red }Goodenum Color { Red }本仓库在 docs/enums.md 以及代码示例 code/es6/enums.ts 中均有完整的枚举教程与可运行示例可作为补充阅读。nullvs.undefined基于场景的三条取舍原则这是风格指南中信息量最大的部分规则按场景分层1. 尽量都不要显式使用对于显式不可用的语义倾向于两种值都不使用。因为这些值通常被用来在值之间保持结构一致性而在 TypeScript 中结构应该由类型来表述Badlet foo { x: 123, y: undefined };Goodlet foo: { x: number, y?: number } { x:123 };上面 Good 版本用可选成员y?: number表达了该属性可能不存在的意图完全不需要显式塞入undefined。更稳妥的做法甚至是返回一个带有效性标记的对象例如{valid: boolean, value?: Foo}让结构自身携带状态信息。2. 一般场景使用undefined在没有特殊约束的普通场景下用undefined而不是nullBadreturn null;Goodreturn undefined;3. 当null是 API 或生态惯例时使用null如果null是某个 API 的既定契约或社区惯例就遵循它。最典型的例子是 Node.js 的 NodeBack 风格回调无错误时error参数为null。Badcb(undefined)Goodcb(null)判断技巧对象用 truthy 检查原始值用 null对对象进行null/undefined判断时直接用 truthy 检查Badif (error null)Goodif (error)对原始值判断是否为 null 或 undefined时使用 null/! null而非/!因为它能同时排除null与undefined且不会误伤其他 falsy 值如、0、falseBadif (error ! null) // does not rule out undefinedGoodif (error ! null) // rules out both null and undefined关于这些语义的深入背景undefined、null以及 truthy 判断的本质可参考 null-undefined 章节 与 truthy 章节。格式化让编译器与tsfmt自动完成TypeScript 编译器自带非常出色的格式化语言服务其默认输出已经足够好能够显著降低团队成员的认知负担。推荐的实操路径命令行自动格式化使用tsfmttypescript-formatter在命令行自动格式化代码IDE 内置格式化atom、VSCode、VS、Sublime 等主流编辑器都内置了格式化支持。格式化示例——注意类型标注的书写方式冒号前无空格冒号后有一个空格foo:spacestring// Space before type i.e. foo:spacestring const foo: string hello;本仓库的示例项目均配有tsconfig.json便于直接复现与验证例如 docs/styleguide/tsconfig.json空配置{}、docs/project/tsconfig.md 则系统讲解了tsconfig.json的配置语义。团队若需要引入自动化格式化与代码检查仓库中 tools 章节 还介绍了 prettier、eslint 等配套工具链的接入方式。引号优先单引号除非需要转义优先使用单引号。理由JavaScript 生态中更多团队采用单引号例如 airbnb、standard、npm、node、google/angular、facebook/react 等且大多数键盘上单引号输入无需按 Shift敲击更省力Prettier 团队也推荐单引号。当然双引号并非没有优点它允许把对象直接复制粘贴为 JSON允许使用其他语言的开发者不切换引号字符还能直接书写撇号apostrophe例如Hes not going.。但作者的观点是既然 JS 社区在这点上已基本达成一致就不必背离。当双引号不便使用时可以尝试使用反引号因为反引号通常更能表达字符串足够复杂的意图对应模板字符串参见 template-strings 章节 与示例 code/es6/template-strings.ts。缩进2 个空格不用 Tab使用 2 个空格缩进不要使用 Tab。理由JS 生态中更多团队采用 2 空格airbnb、idiomatic、standard、npm、node、google/angular、facebook/react 等。TypeScript/VSCode 团队内部使用 4 空格但这在生态中属于明显的例外。若团队偏好 4 空格请优先考虑 Prettier 等自动化工具 来保证全仓库一致而不是靠人工约定。分号显式使用分号使用分号。理由如下显式分号能帮助格式化工具产生一致的结果缺失 ASI自动分号插入可能让新开发者踩坑例如foo() \n (function(){})会被解析为一条语句而非两条行为完全出乎意料TC39 也对此发出过警告。采用显式分号的知名团队包括 airbnb、idiomatic、google/angular、facebook/react 以及 Microsoft/TypeScript 本身。数组类型标注使用Type[]数组类型优先标注为foos: Foo[]而不是foos: ArrayFoo。理由Foo[]读起来更直观TypeScript 团队自身使用这种写法人的大脑对[]有天然的辨识敏感度看到[]就能立刻意识到这是数组。let foos: Foo[] [];文件名默认camelCase组件场景用PascalCase文件名使用camelCase例如utils.ts、map.ts等这是众多 JS 团队的通用惯例。当文件导出的是组件、且框架如 React要求组件采用PascalCase时文件名应与组件名保持一致使用 Pascal 命名例如Accordion.tsx、MyControl.tsx。这有助于保持一致性无需过多思考也是生态中的通行做法。本仓库的源码文件同样遵循此惯例例如 code/compiler/scanner/runScanner.ts、code/types/type-compatibility.ts 等均为camelCase命名。typevs.interface按需求场景选择当你可能需要联合类型或交叉类型时使用typetype Foo number | { someProperty: number }当你需要extends或implements时使用interfaceinterface Foo { foo: string; } interface FooBar extends Foo { bar: string; } class X implements FooBar { foo: string; bar: string; }其他情况就随你当天的心情选择即可作者个人倾向于使用type。关于interface的完整能力可选成员、只读成员、函数签名、索引签名、继承与实现等可阅读 interfaces 章节type别名在联合/交叉/字面量类型上的更多应用可参考 类型系统 与 advanced 章节。或统一使用对 TypeScript 用户来说与在多数场景下都是安全的因为类型系统已经排除了大部分隐式转换的意外但作者统一使用因为 TypeScript 代码库自身就是这么写的。需要留意的是上一节nullvs.undefined中关于用 null同时排除null与undefined的规则与本条并不矛盾——那是有意为之的特例对原始值判断是否为null或undefined时 null是刻意利用宽松相等语义来覆盖两种空值而其余常规比较一律使用以保持严格与可预期。配套资源与验证方式可直接运行的示例docs/styleguide/sample.ts源码与 docs/styleguide/sample.js编译产物演示了类、命名空间、变量、函数的规范命名在编译前后的形态是本指南各条规则最直观的落地样本编译配置docs/styleguide/tsconfig.json 为空配置{}意味着示例采用编译器全部默认行为无需额外选项即可编译运行进一步阅读作者更为坚持的工程实践见 tips 章节其中包含 type assertion、property setters 等话题的详细讨论类型系统的整体脉络可从 类型系统导读 开始。最后需要重申的是风格指南的价值在于减少无谓争论而非制造教条。当团队对某个写法争执不下时把它当作打破平局的默认答案即可真正能长期降低维护成本的是 Prettier/ESLint 等自动化工具 与扎实的类型设计。赞分享教程【免费下载链接】typescript-book:books: The definitive guide to TypeScript and possibly the best TypeScript book :book:. Free and Open Source 项目地址https://gitcode.com/gh_mirrors/ty/typescript-book点击查看免费下载相关推荐roadmap.sh代码规范编码风格与命名约定roadmap.sh代码规范编码风格与命名约定 ? 前言为什么代码规范如此重要 在大型开源项目中一致的代码风格和命名约定是保证代码质量、可维护性和团队协作文档教程知识库OpenUPM自动化构建的10个关键技巧OpenUPM自动化构建的10个关键技巧 OpenUPM作为开源的Unity Package Registry UPM 提供了强大的自动化构建能力。本文将分享Sunshine 游戏串流完整指南30 分钟从家用主机串出第一帧画面Sunshine 游戏串流完整指南30 分钟从家用主机串出第一帧画面 游戏还开着在书房那台电脑里人却瘫在客厅沙发上——拉 HDMI 线嫌乱搬机器更麻烦。S音视频后端上一篇Gevent在数据科学中的终极应用加速Pandas与NumPy运算的完整指南下一篇KOReader电子书阅读器您的多格式阅读专家让电子墨水屏设备重获新生创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价