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

Type alias recursion is resolved eagerly when the alias is generic and its arguments are derived from inferred members of conditional types #37801

Closed
dead-claudia opened this issue Apr 6, 2020 · 1 comment · Fixed by #40002
Assignees
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature feature-request A request for a new feature Fix Available A PR has been opened for this issue In Discussion Not yet reached consensus

Comments

@dead-claudia
Copy link

TypeScript Version: 3.9.0-beta

Search Terms: recursive, recursive generic

Code

type Intersect<U extends any[], R = unknown> =
    ((...u: U) => any) extends ((h: infer H, ...t: infer T) => any)
        ? Intersect<T, R & H>
        : R

const value: Intersect<[{a: number}, {b: number}]> = {
    a: 1,
    b: 2
}

Note: the usual workaround of an immediately-indexed intermediate object type still works.

Expected behavior: It to type check without warnings

Actual behavior:

  • At line 1: Type alias 'Intersect' circularly references itself. (2456)
  • At line 3: Type 'Intersect' is not generic. (2315)
  • At line 6: Type 'Intersect' is not generic. (2315)

Playground Link: Link

Related Issues:

@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label Apr 17, 2020
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 3.9.1 milestone Apr 17, 2020
@weswigham weswigham added Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature feature-request A request for a new feature In Discussion Not yet reached consensus and removed Needs Investigation This issue needs a team member to investigate its status. labels Apr 21, 2020
@weswigham
Copy link
Member

weswigham commented Apr 21, 2020

So, I spent awhile looking into this - first off, this is working as intended right now, and this is in no way a regression as the same behaviors exist far into the past (so almost certainly shouldn't be scheduled for 3.9.1, I'll move it). Our final design for recursive type aliases only allows recursion on class, interface, and tuple types. This means that aliases to anonymous objects, aliases to unions, aliases to conditionals - none of those can be recursive in the final design (I had a prototype with a more expanded implementation, but this is what we ultimately went with).

Now, enable recursive aliasing for these other cases certainly is possible, but it is not free to do so; we can't actually re-purpose the machinery enabling recursive type aliases for class/interface/tuple types for other kinds of aliases at all. It relies on generic object instantiation as a natural point of deferral in the existing instantiation pipeline. We'd need to use the deferred alias/deferred substitution machinery I had in place in my prototype instead. In addition to that, deferral only works when the type constructors which consume those deferred types keep them deferred - patching holes in that logic is what many of our recursive type alias bugfixes for the current implementation have been thus far, and adding essentially a second implementation will mean more work there. Certainly not impossible and, as I said, most of the work has already been prototyped once, but we'd have to revisit our implementation and decide that the usecases the capabilities enable are worth the increased complexity. I could repost the PR with the broader implementation, but there's not much of a point unless we commit to wanting to enable these usecases first~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature feature-request A request for a new feature Fix Available A PR has been opened for this issue In Discussion Not yet reached consensus
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants