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

Simplify ReturningMethod type so that it avoids infinite type recursion #2278

Closed

Conversation

laurisvan
Copy link

Fixes #2277

I am not an expert on TypeScript typings, but this problem seemed very much like the one described at a related blog article , so I tried my stab at it.

It seems to solve the problem, but I cannot guarantee if it causes some other problems. Then again, 'any' typed query builders disregard the problems anyway...

@laurisvan laurisvan force-pushed the fix/simplify-returning-type branch 2 times, most recently from ef8f018 to 27eaba0 Compare May 21, 2022 16:46
@laurisvan laurisvan changed the title Rework AnyQueryBuilder to prevent infinite type recursion problem (TS2589) Simplify ReturningMethod type so that it avoids infinite type recursion May 21, 2022
@niteshrawat1995
Copy link

niteshrawat1995 commented May 30, 2022

@koskimas Can you have look over it please :)

@koskimas
Copy link
Collaborator

koskimas commented May 30, 2022

This is not a fix. It simply turns the result into a AnyQueryBuilder and thus removes all typing.

@koskimas
Copy link
Collaborator

The output is now a function of QB2 which is never assigned, so it takes the "lower bound" type AnyQueryBuilder.

@laurisvan
Copy link
Author

@koskimas Hmm you are absolutely right. How about simply

  interface ReturningMethod {
    <QB extends AnyQueryBuilder>(
      this: QB,
      column: string | string[]
    ): QB extends NumberQueryBuilder<QB>
      ? ArrayQueryBuilder<QB>
      : QB
  }

I must say I'm getting a bit lost on these typings, so please do guide me. The TS 4.7 problem is real, and since that one is the current released version, I think it's better try to solve the problem. The snippet above solves the infinite recursion problem, but I'm not sutre it is still right (I don't claim to understand why the original checks are the way they are).

@ghost
Copy link

ghost commented Jul 1, 2022

I've been having this problem for about a week. We started migrating our projects to node 18. Later we ran into this problem.

@vedtam
Copy link

vedtam commented Jul 11, 2022

Same here!

@laurisvan laurisvan force-pushed the fix/simplify-returning-type branch from 27eaba0 to 581ee8c Compare July 13, 2022 14:10
@laurisvan
Copy link
Author

laurisvan commented Jul 13, 2022

As per discussion, I changed the implementation so that it will return an ArrayQueryBuilder in case of NumberQueryBuilder and the normal QB in any other case. This is the solution that has worked in our cases, but as mentioned above, there might be cases (that I am unaware of) that this solution does not cover.

@koskimas Do you find that as acceptable, or how should we bend it to fix the problem?

@falkenhawk
Copy link
Contributor

@laurisvan It is possible that this exposes a bug in typescript itself. Once someone posted there a reproduction for kind of similar scenario microsoft/TypeScript#47142 (comment) and they reacted accordingly, preparing a fix. Maybe we could give it a shot this time too 🤔

@falkenhawk
Copy link
Contributor

falkenhawk commented Aug 9, 2022

I've browsed typescript repo looking for hints and took one from microsoft/TypeScript#48552 (comment) to try to simplify type definitions which include recursions.

I gave it a shot and extracted the return type incl. conditional to a separate type, ...and it helped in my case. Please try it yourself @laurisvan

  interface ReturningMethod {
    <QB extends AnyQueryBuilder>(
      this: QB,
      column: string | string[]
    ): QB extends ArrayQueryBuilder<QB>
      ? ArrayQueryBuilder<QB>
      : QB extends NumberQueryBuilder<QB>
      ? ArrayQueryBuilder<QB>
      : SingleQueryBuilder<QB>;
  }

  type ReturningQueryBuilder<QB extends AnyQueryBuilder> = QB extends ArrayQueryBuilder<QB>
    ? ArrayQueryBuilder<QB>
    : QB extends NumberQueryBuilder<QB>
      ? ArrayQueryBuilder<QB>
      : SingleQueryBuilder<QB>;

  interface ReturningMethod {
    <QB extends AnyQueryBuilder>(
      this: QB,
      column: string | string[]
    ): ReturningQueryBuilder<QB>;
  }

That said, nobody shared a reproduction case either here or in linked issue #2277, and it would be great to have one to have something to work on instead of trying wild guesses. Simply bumping typescript to 4.7+ on objection repo and running npm run test:typings does not show any error. (as for me, I don't use returning() method at all, but I got hit by this issue in other weird places, e.g. adding modifiers to a model sometimes, but not always, triggers typescript. But i noticed when I commented out returning: ReturningMethod; from objection typings, the ts issue disappeared)

@falkenhawk
Copy link
Contributor

Ok, I goofed. On more thorough check, that did not help. TS still complains TS2589: Type instantiation is excessively deep and possibly infinite.

@laurisvan
Copy link
Author

@falkenhawk Sorry for the very late reply to this one. Did you spot some problem in my suggested solution, so that an alternate solution is still needed?

@vedtam
Copy link

vedtam commented Dec 22, 2022

Any update on this?

@laurisvan
Copy link
Author

Any update on this?

I don't know - I have been perfectly happy with my solution and have not heard whether it is acceptable or not. The earlier comments hinted for reproduction of the case - I believe we all share the same pain that that this appears for large projects, so I'm not sure if we can package this into a regression test or such easily.

@koskimas Just share your wisdom on what should we do, and I'm perfectly happy to do so. :)

@iiq374
Copy link

iiq374 commented Jan 24, 2023

Would love to see this resolved before we need to ditch objection :-/

@vedtam
Copy link

vedtam commented Jan 28, 2023

@koskimas is a great guy, unfortunately he didn't show up for some time either here or on the gitter channel. He could at least share a reason for his decision.

@laurisvan
Copy link
Author

@koskimas is a great guy, unfortunately he didn't show up for some time either here or on the gitter channel. He could at least share a reason for his decision.

I think he has made it clear and understandable at #2335 - no time nor desire to maintain Objection, which I fully understand and respect.

We have been able to live by patching this change on top of an existing release using https://github.com/ds300/patch-package and that removes the immediate need to move away. Having said that, if there is a library that provides a query builder, types, and validation layer and will be maintained in foreseeable future, we are interested.

@lehni lehni self-assigned this Apr 14, 2023
@lehni
Copy link
Collaborator

lehni commented Apr 14, 2023

@kibertoad this is a crucial issue to get fixed. I think we should merge this, but can't fully judge the solution. Would love to get your opinion on it!

@lehni lehni added the typings label Apr 15, 2023
@lehni
Copy link
Collaborator

lehni commented Apr 15, 2023

There were conflicts in the PR so I've merged this locally: c27720b

Thanks for addressing this @laurisvan !

@lehni lehni closed this Apr 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

TypeScript 4.7 Upgrade results in "Type instantiation is excessively deep and possibly infinite."
7 participants