code-style

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Code 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 (
biome.json
) is the source of truth:
  • 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
    import type { ... }
    for type-only imports
  • 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 (
    index.ts
    re-exporting from the same directory); import from the specific module
  • Use
    .ts
    /
    .tsx
    extensions
    in relative imports (not
    .js
    ). The codebase uses TypeScript source extensions for module resolution
  • 优先使用静态导入;除非有合理理由,否则避免动态导入模式
  • 类型仅导入使用
    import type { ... }
    语法
  • 保持导入明确,便于grep检索
  • 保留清晰的分组/顺序(外部依赖、内部别名、相对路径)
  • 在可行的情况下,避免通配符导出/导入,优先使用显式命名导出
  • 避免桶文件(
    index.ts
    重新导出同目录下的模块);直接从具体模块导入
  • 相对导入中使用
    .ts
    /
    .tsx
    扩展名
    (而非
    .js
    )。代码库使用TypeScript源扩展名进行模块解析

TypeScript

TypeScript规范

Base config:
tsconfig.base.json
. Typechecking runs under
tsgo
(TypeScript 7 beta, via
@typescript/native-preview
) — use
tsgo -p tsconfig.json --noEmit
in
typecheck
scripts, never
tsc
.
  • strict: true
    is enabled; keep code strict-clean
  • Module system:
    NodeNext
    + ESM (
    "type": "module"
    in packages/apps)
  • 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
    src/entities/<entity>.ts
    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.
  • Canonical entity schemas should treat system-managed fields such as
    id
    ,
    createdAt
    , and
    updatedAt
    as 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.
  • Enum-like contracts should use literal-string unions or
    as const
    objects, not TypeScript enums.
  • 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
    readonly
    fields for immutable domain data shapes
  • Avoid
    any
    ; use
    unknown
    + narrowing
  • Avoid unnecessary type assertions (
    as { ... }
    ); prefer relying on inferred types from libraries
  • Validate boundary inputs early (API input, queue payloads, external IO)
基础配置文件:
tsconfig.base.json
。类型检查通过**
tsgo
**(TypeScript 7测试版,基于
@typescript/native-preview
)运行——在
typecheck
脚本中使用
tsgo -p tsconfig.json --noEmit
,切勿使用
tsc
  • 已启用
    strict: true
    ;确保代码符合严格模式要求
  • 模块系统:
    NodeNext
    + ESM(packages/apps中设置
    "type": "module"
  • 对于新的领域数据契约,当需要运行时验证时,首先将标准共享结构定义为Zod schema,然后根据该schema或Drizzle schema推导TypeScript类型(视情况而定)。
  • src/entities/<entity>.ts
    中的schema视为标准领域契约。同一领域内或应用/平台边界处的其他schema和类型,应尽可能派生自或复用这些实体结构,而非重复定义相同字段。
  • 标准实体schema应将
    id
    createdAt
    updatedAt
    等系统管理字段视为核心实体字段。除非确实存在需要分离的边界/输入DTO,否则不要将实体拆分为业务负载加上附加的“持久化”包装器。
  • 枚举类契约应使用字面量字符串联合或
    as const
    对象,而非TypeScript枚举。
  • 使用共享领域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:
    UPPER_SNAKE_CASE
    only for true constants; otherwise
    camelCase
    +
    as const
  • Shared base schemas/types that are extended into discriminated unions or related variants should use
    baseXxxSchema
    /
    BaseXxx
    naming rather than
    xxxCommonSchema
    /
    XxxCommon
    .
  • File names favor concise module roots (
    src/index.ts
    ,
    src/server.ts
    ,
    src/main.tsx
    )
  • React component files use kebab-case:
    my-component.tsx
    or
    my-component/index.tsx
    — never
    PascalCase
    file names (e.g.
    MyComponent.tsx
    ). This matches the
    @repo/ui
    convention (
    table-skeleton.tsx
    ,
    form-field.tsx
    , etc.)
  • Package names follow scoped workspace style (
    @app/*
    ,
    @domain/*
    , etc.)
  • 类型/接口/类:
    PascalCase
    (大驼峰)
  • 变量/函数/方法:
    camelCase
    (小驼峰)
  • 常量:仅真正的常量使用
    UPPER_SNAKE_CASE
    (大写蛇形);否则使用
    camelCase
    +
    as 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

生成文件

  • apps/web/src/routeTree.gen.ts
    is auto-generated by TanStack Router — do not manually edit
  • Generated files may be regenerated during builds or dev server runs; commit them when they change but do not modify by hand
  • apps/web/src/routeTree.gen.ts
    由TanStack Router自动生成——请勿手动编辑
  • 生成文件可能会在构建或开发服务器运行期间重新生成;变更时提交它们,但不要手动修改