Skip to content

[FEATURE] Option to exclude type imports from cycle check #58

Description

@ThiloAschebrock

Feature Request

Problem

TypeScript's import type is erased at compile time and creates no runtime dependency. ArchUnitTS currently treats it the same as value imports during cycle detection, causing false-positive failures when types are shared across layers.

Proposed Solution

Add an excludeTypeImports option to haveNoCycles(), which defaults to false for backwards compatibility.

const rule = projectFiles()
  .inFolder('src/**')
  .should()
  .haveNoCycles({ excludeTypeImports: true });

Use Case

import { projectFiles } from 'archunit';

// Only flag cycles caused by runtime imports, not type-only imports
const rule = projectFiles('tsconfig.json')
  .inFolder('src/**')
  .should()
  .haveNoCycles({ excludeTypeImports: true });

await expect(rule).toPassAsync();

🔄 Alternatives Considered

  • .exclude() patterns only works if types are isolated in a dedicated folder, which forces unnatural project structure.
  • Disable rule per folder defeats the purpose of enforcing cycle detection entirely.

📊 Impact Assessment

  • Core architecture testing
  • File dependencies
  • Metrics calculation
  • Slice testing
  • Error messages
  • Test framework integration
  • Performance
  • Documentation

🎨 Implementation Ideas

The TypeScript compiler API exposes isTypeOnly on ImportDeclaration. Annotate dependency graph edges with this flag and filter them out before running the cycle detection algorithm when the option is set. Default behavior is unchanged.

📋 Additional Context

import type was added in TypeScript 3.8. Since then it has become very common, especially because the verbatimModuleSyntax compiler option (TS 5.0+) and the @typescript-eslint/consistent-type-imports lint rule both require its use for type-only imports.

✋ Checklist

  • I have searched existing issues to make sure this isn't a duplicate
  • I have provided a clear use case
  • I have considered the API design
  • I have thought about backward compatibility. See https://github.com/LukasNiessen/ArchUnitTS

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions