Type expansion causes an infinite loop in package, but not in project

111 Views Asked by At

I have a small package called @instantdb/[email protected].

Say I create a simple file that uses it:

import { init } from "@instantdb/admin";

const { query, transact } = init({
  appId: "your-app-id",
  adminToken: "your-admin-token",
});

When I hover over query, intellisense hangs. I notice Code Helper is taking 100% CPU, and tsserver doesn't make progress.

Cause: Type Expansion

When I look into the index.d.ts file inside @instantdb/admin, I see this giant type expansion:

query: <Q extends Query>(query: Exactly<Query, Q>) => Promise<{ [K_1 in keyof Q]: Q[K_1] extends infer T_1 ? T_1 extends Q[K_1] ? T_1 extends object ? T_1 extends infer T_2 extends object ? { [K_2 in keyof T_2 as Exclude<K_2, "$">]: T_1[K_2] extends infer T_3 ? T_3 extends T_1[K_2] ? T_3 extends object ? T_3 extends infer T_4 extends object ? { [K_3 in keyof T_4 as Exclude<K_3, "$">]: T_3[K_3] extends infer T_5 ? T_5 extends T_3[K_3] ? T_5 extends object ? T_5 extends infer T_6 extends object ? { [K_4 in keyof T_6 as Exclude<K_4, "$">]: T_5[K_4] extends infer T_7 ? T_7 extends T_5[K_4] ? T_7 extends object ? T_7 extends infer T_8 extends object ? { [K_5 in keyof T_8 as Exclude<K_5, "$">]: T_7[K_5] extends infer T_9 ? T_9 extends T_7[K_5] ? T_9 extends object ? T_9 extends infer T_10 extends object ? { [K_6 in keyof T_10 as Exclude<K_6, "$">]: T_9[K_6] extends infer T_11 ? T_11 extends T_9[K_6] ? T_11 extends object ? T_11 extends infer T_12 extends object ? { [K_7 in keyof T_12 as Exclude<K_7, "$">]: T_11[K_7] extends infer T_13 ? T_13 extends T_11[K_7] ?  ....

Understandably, VSCode may be suffering trying to evaluate this type.

Package vs File

Now here's the interesting thing. @instantdb/admin is just one file. If copy and paste index.ts into the project:

import { init } from "./admin.ts";

const { query, transact } = init({
  appId: "your-app-id",
  adminToken: "your-admin-token",
});

Then intellisense works: enter image description here

My guess here, is that for some reason, when the code is a sibling file, Typescript doesn't generate the giant type.

Debugging

I am not 100% sure how to debug this. I tried to reproduce the giant type in a typescript playground, but was not able to do this.

So, why is the index.d.ts producing such a giant query expansion? Is there any way I can "force" a repro inside a playground?

0

There are 0 best solutions below