Skip to content

🐛 knip 6 incorrectly reports exports from a namespace that are used in the same file (out of the namespace) #1633

@Jym77

Description

@Jym77

Prerequisites

Reproduction url

https://github.com/Jym77/knip-namespace

Reproduction access

  • I've made sure the reproduction is publicly accessible

Description of the issue

Following up on #1603 (thanks for handling it).
(CodeSandbox seems to be having trouble with the knip repro setup (something about oxc-parser), and CodeBlitz somehow takes forever to (not) start, so I made a separate repo for repro instead).

index.ts:

import { foo, Bar } from "./foo.js"

namespace Foo {
  export type Value = number // not used

  export function foo(): number { // not used
    return 1
  }
}

foo.ts:

export const foo = 1 // imported by index.ts
export const baz = 2

function bar(): Bar.Value { // unused, but not exported
    return Bar.bar()
  }

export namespace Bar { // imported by index.ts
  export type Value = number // used by (top-level) bar

  export function bar(): number { // used by (top-level) bar
    return 1
  }
}

export namespace Baz { // not used at all
  export type Value = number // not used

  export function baz(): number { // not used
    return 1
  }
}

namespace Qux {  // not used, but local only
  export type Value = number  // not used

  export function qux(): number { // not used
    return 1
  }
}

knip output:

Unused exports (2)
baz             src/foo.ts:2:14
Baz  namespace  src/foo.ts:16:18
Unused exported namespace members (2)
Value  Bar  src/foo.ts:9:15
bar    Bar  src/foo.ts:11:19
  • baz is correctly reported.
  • Bar.Value and Bar.bar are both incorrectly reported. They need to be exported for (top-level) bar to access them.
  • Baz is correctly reported as a single entity, it makes sense to not delve into it at this point.
  • Neither Qux.Value nor Qux.qux are reported, despite none of them being used anywhere. Same goes for Foo.Value and Foo.foo (who are in an entry file, not just a project one).

So, it seems that knip detects the Bar usage from index.ts, therefore looks into it in details, but only from the index.ts point of view, thus not seing that its components are used from inside foo.ts and do need to be exported for that.

Of course, the most annoying part is the false positive reporting on Bar.Value and Bar.bar since it breaks CI/CD validation for incorrect reasons…

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions