microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
100.22k stars 12.39k forks source link

RangeError: Maximum call stack size exceeded #59821

Open gentlee opened 2 weeks ago

gentlee commented 2 weeks ago

🔎 Search Terms

RangeError: Maximum call stack size exceeded

🕗 Version & Regression Information

⏯ Playground Link

https://github.com/gentlee/react-redux-cache/commit/ae4159b12ab02110874ffda5383ea8605b5601e7

💻 Code

Probably caused by cycled typing of createCacheReducer -> Cache and Cache -> createCacheReducer in src/reducer:

export const createCacheReducer = <N extends string, T extends Typenames, QP, QR, MP, MR>(
   actions: ReturnType<typeof createActions<N, T, QR, MR>>,
   typenames: Cache<N, T, QP, QR, MP, MR>['typenames'],
   queries: Cache<N, T, QP, QR, MP, MR>['queries'],
   mutations: Cache<N, T, QP, QR, MP, MR>['mutations'],
   cacheOptions: Cache<N, T, QP, QR, MP, MR>['options']
   ...

🙁 Actual behavior

yarn tsc throws:

RangeError: Maximum call stack size exceeded
    at typeToTypeNodeWorker (typescript/lib/tsc.js:44218:42)
    at typeToTypeNodeHelper (/typescript/lib/tsc.js:44214:32)
    at typeToTypeNodeWorker (ypescript/lib/tsc.js:44438:42)
    at typeToTypeNodeHelper (typescript/lib/tsc.js:44214:32)
    at mapToTypeNodes (typescript/lib/tsc.js:44974:40)
    at typeToTypeNodeWorker (typescript/lib/tsc.js:44355:45)
    at typeToTypeNodeHelper (typescript/lib/tsc.js:44214:32)
    at mapToTypeNodes (typescript/lib/tsc.js:44974:40)
    at typeToTypeNodeWorker (typescript/lib/tsc.js:44355:45)
    at typeToTypeNodeHelper (typescript/lib/tsc.js:44214:32)

🙂 Expected behavior

Should be without errors.

Additional information about the issue

In main branch of the repo problem is not happening.

it started happening in support-multiple-caches branch (1 commit ahead) mostly after code from createActions file was added and used.

Andarist commented 2 weeks ago

"Probably caused by this code" is not exactly a repro case. Can you slim down ur repo to the required bits that lead to this bug?

gentlee commented 2 weeks ago

@Andarist tried, but seems that almost all repo code is needed. Btw fixed it already by removing cycled typing, in the next commit.

Interesting that in prev commit cycles also existed but issue did not happen and everything worked, but after adding changes in that commit tsc started crashing.

gentlee commented 2 weeks ago

FYI Overall repo is the best example of very black TS magic thats required for proper typing in some cases.

And also would be great that we don't need as in switch/case for generic literals:

// src/reducer.ts
switch (action.type) {
  case actions.updateQueryStateAndEntities.type: {
    const {
      queryKey,
      queryCacheKey,
      state: queryState,
      entityChagnes,
    } = action as ReturnType<typeof actions.updateQueryStateAndEntities> // this line should be just `} = action`
Andarist commented 2 weeks ago

This crashes when trying to serialize the type of this createCacheReducer here: https://github.com/gentlee/react-redux-cache/blob/ae4159b12ab02110874ffda5383ea8605b5601e7/src/types.ts#L46

FWIW, it errors because it can't find applicable signatures for this instantiation expression and it tries to report this error:

"Type '{0}' has no signatures for which the type argument list is applicable."

That leads to serializing this type in the first place.

Andarist commented 2 weeks ago

I started with a repro like this: TS playground but I managed to reduce it even further (TS playground):

const createCacheReducer = <N extends string, QR>(
  queries: Cache<N, QR>["queries"],
) => {
  const queriesMap = {} as QR;

  const initialState = {
    queries: queriesMap,
  };

  return (state = initialState) => state;
};

export type Cache<N extends string, QR> = {
  queries: {
    [QK in keyof QR]: ReturnType<typeof createCacheReducer<QR>>;
  };
};