Repository: TypeScript
Issue: Provide flag for projects to ban compile-time side-effects in root files
Labels: Suggestion,Awaiting More Feedback

## Search Terms

- pure
- side-effects
- elision
- global-modifying

## Suggestion

<!-- A summary of what you'd like to see added or changed -->
A new `tsconfig` flag should be added that bans compile-time side-effects in project root files. This idea was [originally proposed by @andrewbranch in response to an external pull request](https://github.com/microsoft/TypeScript/pull/40966#issuecomment-705696203). The flag name can be discussed further, but examples might be `noTypingSideEffects`, `noGlobalModifyingModules`, `noCompileTimeSideEffects`, `pure` etc. The phrase *"compile-time side-effects"* refers to anything that can affect type-checking dependent source files outside of the standard `export` syntax.

The TypeScript features that allow source files to modify typing information outside of their file scope include the following:

- [ambient modules](https://www.typescriptlang.org/docs/handbook/modules.html#ambient-modules)
- [module augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation)
- [global augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation)
- [global variables](https://www.typescriptlang.org/docs/handbook/declaration-files/by-example.html#global-variables)
- [global functions](https://www.typescriptlang.org/docs/handbook/declaration-files/by-example.html#global-functions)
- [triple-slash directives](https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html#-reference-path-)
- ... and potentially more

With this flag enabled, an error should appear on any usages of the above.

It may be worth allowing the flag (or a separate option) to specify allowlisted files that are expected to have side-effects. Notably, webpack's `sideEffects` option is  a `boolean | string[]` type for this purpose.

### Comparison to bundler tree-shaking

This idea is inspired by bundler tree-shaking, but focuses on side-effects at compile-time rather than runtime. The ideas are similar but different enough to warrant a specific TypeScript flag.

For example, a file that calls `console.log` on import has a runtime side-effect bundlers may care about but does not have any affect on typing. The allowlisted array of files with side-effects will likely be different between TypeScript and bundlers.

## Use Cases

Banning compile-time side-effects allows future speed improvements. Notably, the compiler can now know whether source files and its import tree can be safely elided from a `Program` if its exported identifiers are unused. This has potentially significant speed and memory improvements depending on the source file graph of a program.

A quick and unfinished implementation that only looks at `export { ... } from "..."` syntax was created in PR #40966.

## Examples

For a program with the following files, TypeScript should output:

> a.ts(2,0): 'someGlobalVar' is a global variable, which is banned by the 'noTypingSideEffects' compiler option.

```json
// tsconfig.json
{
  "compilerOption": {
    "noTypingSideEffects": true
  },
  "files": ["index.ts", "a.ts"]
}
```
```ts
// index.ts
import { a } from "./a";

console.log(someGlobalVar);
```
```ts
// a.ts
export const a = 1;
declare var someGlobalVar = 2;
```



<!-- Show how this would be used and what the behavior would be -->

## Checklist

My suggestion meets these guidelines:

* [x] This wouldn't be a breaking change in existing TypeScript/JavaScript code
* [x] This wouldn't change the runtime behavior of existing JavaScript code
* [x] This could be implemented without emitting different JS based on the types of the expressions
* [x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
* [x] This feature would agree with the rest of [TypeScript's Design Goals](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals).