knip icon indicating copy to clipboard operation
knip copied to clipboard

Object property enumeration methods used on enum reporting as unused exported enum members

Open shawnmcknight opened this issue 1 year ago • 3 comments

I've created a reproduction at https://github.com/shawnmcknight/knip-enum-object-values.

In this scenario, there is an enum with initializers:

export enum Fruits {
  apple = "apple",
  orange = "orange",
}

That enum is imported and run through any of the Object property enumerators:

const fruitKeys = Object.keys(Fruits);
const fruitValues = Object.values(Fruits);
const fruitEntries = Object.entries(Fruits);

With this code, each enum member is reported as unused by knip, but effectively every enumerated value is being used. I'm not sure I would consider Object.keys to be "using" the enum member, but both Object.values and Object.entries are consuming the entirety of the enumeration.

Please let me know if there is anything else I can provide to assist!

shawnmcknight avatar Jun 25 '24 21:06 shawnmcknight

Knip doesn't really support any kind of dynamics like the one reported. It's basically mostly just direct references or "dotted" references (for e.g. namespaces, enum members).

However, perhaps we could such handle situations a bit like https://knip.dev/guides/namespace-imports and when an enum (or namespace) is used as an argument in eg. Object.keys and perhaps other enumerations/iterations we consider them all "referenced".

webpro avatar Jun 26 '24 21:06 webpro

This situation does sound a lot like the namespace example. As noted there, you don't really know if the namespace is being used by send, but more than likely you want to consider it to be completely referenced. This situation is pretty much the same -- its unknown whether each enum member is actually being used, but you probably don't want it to be reported.

To elaborate a bit on where this presented itself, we have scenarios where the enum members needed to be turned into an array of strings for validation purposes (e.g. mongoose schema enum constraints). The enum members might not need to be referenced directly since they might simply flow in and out as the initialized strings. The enum makes a nice container for these values and when necessary, individual enum members could be referenced, even though they all don't have to be.

shawnmcknight avatar Jun 26 '24 22:06 shawnmcknight

I have the exact same situation and one more where it is used as a type only:

export enum Gender {
	MALE = 'male',
	FEMALE = 'female',
	DIVERS = 'divers',
	ANY = 'any',
}

export const genders = Object.values(Gender)

export interface Profile {
	gender?: Gender
}

muuvmuuv avatar Jul 08 '24 21:07 muuvmuuv

You can this before the release:

npm i -D https://pkg.pr.new/knip@e4bada4

Note that the behavior is not the same as with the namespace imports: enum usage in an Object enumeration method means no members will be reported. Regardless of whether also one or more members are referenced somewhere. Happy to discuss if this is surprising behavior.

webpro avatar Oct 05 '24 15:10 webpro

:rocket: This issue has been resolved in v5.32.0. See Release 5.32.0 for release notes.

Using Knip in a commercial project? Please consider becoming a sponsor.

webpro avatar Oct 06 '24 18:10 webpro