Repository: TypeScript
Issue: Possible memory-leak or infinite recursion in type-checking algorithm.
Labels: Needs More Info

# Bug Report

### 🔎 Search Terms
memory-leak type-checking tsc memory-limit not-enough-memory

### 🕗 Version & Regression Information
- This is a crash
- I have checked this on 4.5.4 and 4.5.5

### ⏯ Reproduce
I was developing a SQL query builder with TS [main repo](https://github.com/MRNafisiA/type-query) and I experienced some problems when I was using it.  [reproduce repo](https://github.com/MRNafisiA/too-much-inferring)

```
git clone https://github.com/MRNafisiA/too-much-inferring
cd ./too-much-inferring
yarn install
./node_modules/jest/bin/jest.js
```
the test will be 
1- type checked
2- transpiled 
3- ran successfully. ( test will fail because it can't connect to the database but It is OK. the point is, first phase(type checking) passed.)

go to ./src/index.ts
comment lines 22 and 23 ( They are marked as "Correct" )
uncomment lines 25 and 26 ( They are marked as "Incorrect" )
and now try
```
./node_modules/jest/bin/jest.js
```
It will eat up your CPU and Memory and will be failed with memory-limit error after about 10 minutes. Obviously It is not a memory problem, because previous test executed with the same memory. you can increase memory with below command.
```
node --max-old-space-size=4096 ./node_modules/jest/bin/jest.js
```
But It will not help.  
Error text ( in case you don't want to wait 10 minutes)
```
<--- Last few GCs --->

[1458:0x7fc31ca00000]   331911 ms: Mark-sweep (reduce) 2043.6 (2082.4) -> 2042.7 (2082.4) MB, 3281.5 / 0.0 ms  (average mu = 0.141, current mu = 0.002) allocation failure scavenge might not succeed
[1458:0x7fc31ca00000]   335398 ms: Mark-sweep (reduce) 2043.9 (2082.4) -> 2043.0 (2082.7) MB, 3478.4 / 0.0 ms  (average mu = 0.074, current mu = 0.002) allocation failure scavenge might not succeed


<--- JS stacktrace --->

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
 1: 0x10be15225 node::Abort() [/usr/local/bin/node]
 2: 0x10be153a8 node::OnFatalError(char const*, char const*) [/usr/local/bin/node]
 3: 0x10bf8c9c7 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]
 4: 0x10bf8c963 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]
 5: 0x10c12afe5 v8::internal::Heap::FatalProcessOutOfMemory(char const*) [/usr/local/bin/node]
 6: 0x10c12f00b v8::internal::Heap::RecomputeLimits(v8::internal::GarbageCollector) [/usr/local/bin/node]
 7: 0x10c12b8ec v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [/usr/local/bin/node]
 8: 0x10c128d9a v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/usr/local/bin/node]
 9: 0x10c1360f0 v8::internal::Heap::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/usr/local/bin/node]
10: 0x10c136171 v8::internal::Heap::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/usr/local/bin/node]
11: 0x10c1030c7 v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationType, v8::internal::AllocationOrigin) [/usr/local/bin/node]
12: 0x10c4af0ae v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [/usr/local/bin/node]
13: 0x10c8510b9 Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit [/usr/local/bin/node]
```
  
  
```ts
// Correct
const removingIDs: TagGroup['id'][] = [];
const editingIDs: TagGroup['id'][] = [];

// Incorrect
const removingIDs = [];
const editingIDs = [];
```
As you can see, the difference is only on type definition. correct approach define types explicitly, but in incorrect approach, typescript must infer it. I think It is not hard to infer because array is modified only on one place.  

### 🙁 Actual behavior and 🙂 Expected behavior
So, what is the problem? Actually, I don't know. but I'm sure, I must get type error or successful build but out-of-memory after 10 minutes  is not expected.

Thanks!  
PS: After uncommenting Incorrect section, your IDE will hang(same reason as typescript type-checking hangs) and does not work properly. It will work with heavy lag and delay. to fix this, comment incorrect section and restart you IDE.
PS: if you think index.js has weird logic, It's because I have extracted it from a real project. I tried to narrow it down for simplicity. So, It makes sense that It doesn't make sense! but the code inside type-query must be in good shape. If you found a problem or bad design, I would be appreciated if you point it out.

EDIT:
You can use `tsc` command and get same result. I only used `jest` because It's easier in IDE. the main problem is in type-checking not transpiling or running.

EDIT 2:
I was reading TypeScript 4.5 release notes and I saw this [tail-recursion](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html#tail-recursion-elimination-on-conditional-types). I have infinite recursion in [Expression type](https://github.com/MRNafisiA/too-much-inferring/blob/main/src/type-query/types/Expression.ts). but It seemed that type script can not detected in this particular example.