Skip to content

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

Open

Description

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[]]; }.

Activity

  1. jfet97 commented on Dec 25, 2022

    @jfet97
    ContributorAuthor

    Pinging Mateusz BurzyΕ„ski (@Andarist) as requested from him.

  2. Andarist commented on Dec 26, 2022

    @Andarist
    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 πŸ˜‰

  3. fatcerberus commented on Dec 26, 2022

    @fatcerberus

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

  4. Andarist commented on Dec 26, 2022

    @Andarist
    Contributor

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs InvestigationThis issue needs a team member to investigate its status.

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions