Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detect dead exports as well as per-module dead code #30517

Open
markboyall opened this issue Mar 21, 2019 · 5 comments
Open

Detect dead exports as well as per-module dead code #30517

markboyall opened this issue Mar 21, 2019 · 5 comments
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript

Comments

@markboyall
Copy link

Search Terms

dead code

Suggestion

Add a feature to detect dead code not just within modules, but within the build as a whole.

I've looked at #16939 which is currently locked so can't comment there. This really does need to be part of the Typescript compiler as no other program is really going to understand all the subtleties; the emitted JS doesn't contain all the information about interfaces and that kind of thing. Furthermore, this is not a file level operation- you're talking about tracking each individual interface/function/etc and not files. With these two factors it's no surprise that there are no current tools that can accomplish this- you would have to reimplement the compiler.

This would probably not be useful for library projects, as by definition things they export are not dead, therefore a separate compiler switch would be useful that application developers can enable.

The exact behaviour should be that exported top-level declarations may be considered "dead" if they are not visibly imported, as well as if they are not used from within the current module. The compiler will error on unused exports. The compiler should detect dynamic imports if the module path is hardcoded- the compiler already supports proper type inference in this case so feels like the compiler can already figure this one out.

This does not have to extend to properties/members of classes or anything like that- that can be a future improvement.

The compiler should ignore exports with a leading underscore, offer a built-in decorator to override a declaration as used, or both to handle any weird cases or entry points.

Use Cases

We already detect dead code across individual files, but not across our whole project. We wish to do so across the entire project. We currently inspect runtime metadata of modules imported/exported as a unit test; unfortunately this is limited because TypeScript will emit modules that don't have any runtime code (e.g. just define an interface) but won't emit references to them. In addition, this approach can only detect whole modules as dead and not parts of them.

Examples

The user would simply turn this on in their tsconfig.json, mark up the entry point for their app, then run the build.

Checklist

My suggestion meets these guidelines:

  • [*] This wouldn't be a breaking change in existing TypeScript/JavaScript code- existing users don't have to turn on the flag if they don't want to and it probably shouldn't be part of --strict either.
  • [*] This wouldn't change the runtime behavior of existing JavaScript code
  • [*] This could be implemented without emitting different JS based on the types of the expressions
  • [*] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • [*] This feature would agree with the rest of TypeScript's Design Goals.
@RyanCavanaugh RyanCavanaugh added Suggestion An idea for TypeScript Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature labels Mar 21, 2019
@mjbvz
Copy link
Contributor

mjbvz commented Apr 15, 2019

Related #29293

@wh1t3cAt1k
Copy link

This is sorely needed and will save lots of precious time for our project. As we have a policy to cover every public member with tests, often we end up explicitly covering public class methods that could safely be made private, which is an obvious waste of time - such code would've been exercised through other members' tests anyway.

@joshribakoff
Copy link

This can be done today, I do it with a separate static analyzer I wrote, using the TS language service to jump to definition recursively to walk the references. However, often “dead” code still has tests so it won’t show up as dead, or “live” code may be exported for consumption outside the repo.

It’s very company/project specific. It will vary from project to project what counts as a test, or which outside repos to also search for references.

@fatihturgut
Copy link

is there any news about this issue?

@jasonwilliams
Copy link

jasonwilliams commented Jun 10, 2022

Sometimes I export something with a plan to use it but end up refactoring later and forgetting to remove the export. It would be great if there's a way to detect these. ESLint would not be able to do this as it would require indexing the whole project, something TypeScript already does.

There are some plugins and third party extensions that do this so it must be possible, but it would be cleaner to see this implemented in TypeScript itself.

It's true what Matt is saying that something exported is assumed to be used but it would be great if there's some way to have a warning that a (non-root) export is unused.

We currently assume that exported members form a public API and therefore are always used. We could try to detect that a certain set of files are an API entrypoints, and then mark unused internal exports. Not sure if there are any issue already tracking this

Yes, I think the best option would be to detect that a symbol exported never reaches the root of a project and couldn't be part of the "public API" anyway, in which case, these are good candidates for marking as unused. As TypeScript is already indexing every symbol is this information already available?

Some prior art:

Slightly related to: #29293

CC @andrewbranch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

7 participants