deslop/private-type-leak

Disallow exporting a symbol whose signature references a locally-declared, non-exported type.

  • Category: Architecture
  • Severity: warn
  • Source: deslop-js
  • Framework: global
  • Enabled when: react-doctor deadCode analysis enabled (default true); whole-project scan only — skipped in --diff/--staged modes
  • Documentation: https://github.com/millionco/deslop-js

Validation prompt

Use this to decide whether a fired diagnostic is real or a false positive.

Fires (confidence always high) when detectPrivateTypeLeaks finds an exported declaration — a function/arrow/function-expression's params or return, a typed const, or a class method/property — whose signature names a type or interface declared in the same module but absent from that module's exported names, with reason \"<exportName>'s signature references <typeName>, declared locally but not exported — consumers can't satisfy the type without importing it\". False positive: the type is intentionally opaque/internal so the export is meant to be used positionally (e.g. an options bag callers only ever spread or pass through and never annotate), OR the type is in fact re-exported from a different module — the detector only checks the same file's exportedNames and explicitly does not chase aliased re-export paths, so a export type { Foo } from './foo' barrel elsewhere makes this a false positive.

Fix prompt

Use this once validation confirms the diagnostic is real.

Add the leaked type to the module's public surface so consumers can name it: change interface Options { ... } / type Options = ... to export interface Options / export type Options, or add export type { Options } to the file (and to the package barrel if one exists). If the type genuinely should stay internal, inline its shape into the exported signature so nothing private is referenced, e.g. export function run(opts: { retries: number }): void instead of referencing a hidden Options. Leaking a private type means callers can construct the argument but cannot type a variable or wrapper that holds it. See https://github.com/millionco/deslop-js