Skip to content

Broken double inference step in variadic tuple types when rest elements come into play #52017

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

Open
jfet97 opened this issue Dec 25, 2022 · 4 comments
Labels
Needs Investigation This issue needs a team member to investigate its status.
Milestone

Comments

@jfet97
Copy link
Contributor

jfet97 commented Dec 25, 2022

Bug Report

πŸ”Ž Search Terms

variadic tuple type, rest element, infer, unknown[]

It might be related to #51138 and #51157

πŸ•— Version & Regression Information

This is the behavior in every version I tried, nightly included.

⏯ Playground Link

Playground link with relevant code

Minimal repro of the problem

πŸ’» Code

The double inference step is needed to preserve labels of both the first element and the rest.

type HEAD_TAIL<T extends readonly any[]> =
  T extends readonly [any?, ...infer TAIL]
  ? 
    T extends readonly [...infer HEAD, ...TAIL]
    ? {
      HEAD: HEAD;
      TAIL: TAIL;
    }
    : never
  : never;

πŸ™ Actual behavior

The following is inferred as { HEAD: unknown[]; TAIL: [b: 2, ...c: 3[]]; }

type test3 = HEAD_TAIL<[a:1, b:2, ...c: 3[]]>

πŸ™‚ Expected behavior

The expected type is { HEAD: [a:1]; TAIL: [b: 2, ...c: 3[]]; }.

@jfet97
Copy link
Contributor Author

jfet97 commented Dec 25, 2022

Pinging @Andarist as requested from him.

@Andarist
Copy link
Contributor

Potentially a simpler version (with a single step) of this conditional type could work here as well but it doesn't work either:

type HEAD_TAIL<T extends readonly any[]> = T extends readonly [
  ...infer HEAD extends [any?],
  ...infer TAIL
]
  ? {
      HEAD: HEAD;
      TAIL: TAIL;
    }
  : never;

While #51157 improves the situation a little bit for the extends [any?] part, it doesn't handle 2 (or more) variadic elements in the target type here. There is no code to support such a case there - which kinda makes sense since this didn't make a lot of sense prior to infer extends syntax and that is a fairly new addition.

Fixing this would require rewriting the whole part of inferFromObjectTypes that relates to tuples. Right now the logic there tries to "pattern match" some specific situations but with infer extends we could support a dynamic number of variadic elements (if they are constrained with extends).

For similar reasons your original repro here doesn't work - such a mix of a variadic and rest elements is just not handled at all by the current logic.

I'll keep thinking about how to rewrite this whole bit to handle both cases - if you'd like to brainstorm how the improved algorithm could work, my DMs are open πŸ˜‰

@fatcerberus
Copy link

Isn't [ ...infer HEAD, ...infer TAIL ] ambiguous since the input tuple could be any length and the choice of where to split is arbitrary?

@Andarist
Copy link
Contributor

in @jfet97’s example TAIL is being simply spread, in my example HEAD has a fixed-size constraint so it isn’t ambiguous

@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label Jan 24, 2023
@RyanCavanaugh RyanCavanaugh added this to the Backlog milestone Jan 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Investigation This issue needs a team member to investigate its status.
Projects
None yet
Development

No branches or pull requests

4 participants