code-style
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCode style, TypeScript, and naming
代码风格、TypeScript与命名规则
When to use: Biome formatting, import style, strict TypeScript, naming (including React file names), or generated files. For where domain code lives, see architecture-boundaries.
适用场景:Biome格式化、导入风格、严格TypeScript、命名规则(包括React文件名)或生成文件相关规范。关于领域代码的存放位置,请查看架构边界。
Code style (Biome)
代码风格(Biome)
Biome config () is the source of truth:
biome.json- Indentation: 2 spaces
- Max line width: 120
- Strings: double quotes
- Semicolons: as needed
- Ignore generated/output paths: ,
dist/**,coverage/**,.turbo/**,node_modules/**,**/*.gen.ts**/models.dev.json - Prefer package-local formatting:
pnpm --filter @app/api format
Biome配置文件()是权威依据:
biome.json- 缩进:2个空格
- 最大行宽:120字符
- 字符串:双引号
- 分号:按需使用
- 忽略生成/输出路径:,
dist/**,coverage/**,.turbo/**,node_modules/**,**/*.gen.ts**/models.dev.json - 优先使用包级格式化命令:
pnpm --filter @app/api format
Imports
导入规范
- Prefer static imports; avoid dynamic import patterns unless justified
- Use for type-only imports
import type { ... } - Keep imports explicit and grep-friendly
- Preserve clear grouping/order (external, internal alias, then relative)
- Avoid wildcard exports/imports when explicit named exports are practical
- Avoid barrel files (re-exporting from the same directory); import from the specific module
index.ts - Use /
.tsextensions in relative imports (not.tsx). The codebase uses TypeScript source extensions for module resolution.js
- 优先使用静态导入;除非有合理理由,否则避免动态导入模式
- 类型仅导入使用语法
import type { ... } - 保持导入明确,便于grep检索
- 保留清晰的分组/顺序(外部依赖、内部别名、相对路径)
- 在可行的情况下,避免通配符导出/导入,优先使用显式命名导出
- 避免桶文件(重新导出同目录下的模块);直接从具体模块导入
index.ts - 相对导入中使用/
.ts扩展名(而非.tsx)。代码库使用TypeScript源扩展名进行模块解析.js
TypeScript
TypeScript规范
Base config: . Typechecking runs under (TypeScript 7 beta, via ) — use in scripts, never .
tsconfig.base.jsontsgo@typescript/native-previewtsgo -p tsconfig.json --noEmittypechecktsc- is enabled; keep code strict-clean
strict: true - Module system: + ESM (
NodeNextin packages/apps)"type": "module" - For new domain data contracts, define the canonical shared shape as a Zod schema first when runtime validation is required, then infer TypeScript types from that schema or from Drizzle schemas where appropriate.
- Treat schemas in as the canonical domain contract. Schemas and types elsewhere in the same domain or at app/platform boundaries should derive from or reuse those entity shapes whenever practical instead of restating identical fields.
src/entities/<entity>.ts - Canonical entity schemas should treat system-managed fields such as ,
id, andcreatedAtas core entity fields. Do not split an entity into a business payload plus an appended "persistence" wrapper unless there is a truly distinct boundary/input DTO that needs that separation.updatedAt - Enum-like contracts should use literal-string unions or objects, not TypeScript enums.
as const - Use shared domain schemas to validate data crossing from app/platform boundaries into domain use-cases.
- If a boundary schema must differ materially from the entity shape, reuse domain constants, field schemas, and literal unions before introducing duplicated inline limits or sentinel values.
- Configurable thresholds, weights, debounce windows, sentinel values, and similar tunables should live in named constants inside the owning domain package rather than as scattered inline literals.
- Types and schemas that exist only as the inputs of one use-case should stay in that use-case file unless several use-cases truly share the same contract.
- Prefer explicit domain types/interfaces over loose objects
- Methods/functions with more than one argument should default to a single named-arguments object rather than positional arguments
- Use fields for immutable domain data shapes
readonly - Avoid ; use
any+ narrowingunknown - Avoid unnecessary type assertions (); prefer relying on inferred types from libraries
as { ... } - Validate boundary inputs early (API input, queue payloads, external IO)
基础配置文件:。类型检查通过****(TypeScript 7测试版,基于)运行——在脚本中使用,切勿使用。
tsconfig.base.jsontsgo@typescript/native-previewtypechecktsgo -p tsconfig.json --noEmittsc- 已启用;确保代码符合严格模式要求
strict: true - 模块系统:+ ESM(packages/apps中设置
NodeNext)"type": "module" - 对于新的领域数据契约,当需要运行时验证时,首先将标准共享结构定义为Zod schema,然后根据该schema或Drizzle schema推导TypeScript类型(视情况而定)。
- 将中的schema视为标准领域契约。同一领域内或应用/平台边界处的其他schema和类型,应尽可能派生自或复用这些实体结构,而非重复定义相同字段。
src/entities/<entity>.ts - 标准实体schema应将、
id和createdAt等系统管理字段视为核心实体字段。除非确实存在需要分离的边界/输入DTO,否则不要将实体拆分为业务负载加上附加的“持久化”包装器。updatedAt - 枚举类契约应使用字面量字符串联合或对象,而非TypeScript枚举。
as const - 使用共享领域schema验证从应用/平台边界进入领域用例的数据。
- 如果边界schema必须与实体结构存在实质性差异,在引入重复的内联限制或标记值之前,先复用领域常量、字段schema和字面量联合。
- 可配置阈值、权重、防抖窗口、标记值及类似可调参数,应存放在所属领域包内的命名常量中,而非分散的内联字面量。
- 仅作为单个用例输入的类型和schema应保留在该用例文件中,除非多个用例确实共享相同契约。
- 优先使用显式领域类型/接口,而非松散对象
- 具有多个参数的方法/函数默认应使用单个命名参数对象,而非位置参数
- 不可变领域数据结构使用字段
readonly - 避免使用;使用
any+ 类型收窄unknown - 避免不必要的类型断言();优先依赖库的类型推导
as { ... } - 尽早验证边界输入(API输入、队列负载、外部IO)
General principles
通用原则
- Prefer minimal, explicit abstractions — YAGNI
- Avoid comments except for genuinely non-obvious reasoning
- 优先使用简洁、明确的抽象——YAGNI(无需过度设计)
- 除非是真正非显而易见的逻辑,否则避免添加注释
Domain module layout
领域模块布局
- Canonical entity schemas and inferred entity types belong in .
src/entities/<entity>.ts - Domain package constants belong in .
src/constants.ts - Domain package errors belong in .
src/errors.ts - Small domain-scoped shared helpers such as predicates or lifecycle helpers belong in .
src/helpers.ts
- 标准实体schema和推导的实体类型存放在中。
src/entities/<entity>.ts - 领域包常量存放在中。
src/constants.ts - 领域包错误定义存放在中。
src/errors.ts - 小型领域范围内的共享辅助工具(如谓词或生命周期辅助函数)存放在中。
src/helpers.ts
Naming conventions
命名规范
- Types/interfaces/classes:
PascalCase - Variables/functions/methods:
camelCase - Constants: only for true constants; otherwise
UPPER_SNAKE_CASE+camelCaseas const - Shared base schemas/types that are extended into discriminated unions or related variants should use /
baseXxxSchemanaming rather thanBaseXxx/xxxCommonSchema.XxxCommon - File names favor concise module roots (,
src/index.ts,src/server.ts)src/main.tsx - React component files use kebab-case: or
my-component.tsx— nevermy-component/index.tsxfile names (e.g.PascalCase). This matches theMyComponent.tsxconvention (@repo/ui,table-skeleton.tsx, etc.)form-field.tsx - Package names follow scoped workspace style (,
@app/*, etc.)@domain/*
- 类型/接口/类:(大驼峰)
PascalCase - 变量/函数/方法:(小驼峰)
camelCase - 常量:仅真正的常量使用(大写蛇形);否则使用
UPPER_SNAKE_CASE+camelCaseas const - 被扩展为区分联合或相关变体的共享基础schema/类型,应使用/
baseXxxSchema命名方式,而非BaseXxx/xxxCommonSchema。XxxCommon - 文件名倾向于简洁的模块根命名(,
src/index.ts,src/server.ts)src/main.tsx - React组件文件使用短横线命名法(kebab-case):或
my-component.tsx——绝不使用大驼峰文件名(如my-component/index.tsx)。这与MyComponent.tsx的约定一致(例如@repo/ui,table-skeleton.tsx等)form-field.tsx - 包名遵循作用域工作区风格(,
@app/*等)@domain/*
Generated files
生成文件
- is auto-generated by TanStack Router — do not manually edit
apps/web/src/routeTree.gen.ts - Generated files may be regenerated during builds or dev server runs; commit them when they change but do not modify by hand
- 由TanStack Router自动生成——请勿手动编辑
apps/web/src/routeTree.gen.ts - 生成文件可能会在构建或开发服务器运行期间重新生成;变更时提交它们,但不要手动修改