不能。eslint仅分析ast,不理解ddd语义,需将aggregate、domainevent等约束转化为基于路径、命名、导入关系和类结构的可检测代码模式。

ESLint 能否直接检测 DDD 概念?
不能。ESLint 本身只分析 AST,不理解 Aggregate、DomainEvent、Repository 这类业务语义。它只能识别语法结构(如类声明、函数调用、导入路径),无法判断一个类是否“应该”是值对象还是实体——这需要你把 DDD 约束翻译成可检测的代码模式。
如何把 DDD 规则转成 ESLint 可执行的规则
核心思路是:用文件路径 + 命名约定 + 导入关系 + 类声明结构,组合出可验证的契约。例如:
-
src/domain/user/下的*.ts文件,若导出类名以Aggregate结尾,必须继承自BaseAggregate(通过ClassDeclaration.superClassAST 节点校验) -
src/domain/**/events/下的文件,导出的类必须实现DomainEvent接口(检查implements子句或类型断言) -
src/infrastructure/persistence/中的文件,禁止直接importsrc/application/或src/domain/(用ImportDeclaration+source.value正则匹配拦截) -
src/domain/**/value-objects/中的类,必须是export class且不含private构造函数以外的任何方法(遍历ClassBody.body,过滤掉Constructor和MethodDefinition)
实际落地要绕开哪些坑
很多团队卡在第一步:写了个规则但没生效。常见原因包括:
- 插件未在
.eslintrc.js的plugins数组里注册,或未在rules中显式启用(如"my-ddd/no-domain-import-in-infrastructure": "error") - 规则依赖路径解析,但项目用了
tsconfig.json的paths别名,ESLint 默认不处理——得配eslint-import-resolver-typescript并在settings里指定project - 自定义规则里用
context.getSourceCode().getText()做字符串匹配,结果被 TypeScript 编译前的装饰器、泛型等干扰;应优先用 AST 节点类型和属性判断(如node.type === 'ClassDeclaration') - VSCode ESLint 插件默认只校验打开的文件,而 DDD 层间越界常发生在未打开的
infrastructure文件里——需确保eslint.workingDirectories包含整个src/,且eslint.run设为"onSave"或"onType"
为什么建议从 “层间依赖” 和 “命名空间约束” 入手
DDD 最容易违反、也最易自动化的就是这两类。比起强行校验“这个类是否符合聚合根生命周期”,不如先守住底线:
- 禁止
domain→infrastructure的反向 import(用no-restricted-imports配置路径白名单) - 强制
application/use-cases只能 importdomain和shared(同上) - 所有
src/domain/**/entities/下的类名必须含Entity后缀(用no-invalid-filename自定义规则)
这些规则上线后,开发者立刻能感知到约束,后续再逐步叠加更细粒度的领域语义校验。别一上来就写 validate-aggregate-invariants——AST 里根本找不到“不变量”的节点。











