'label on Tuple after manipulation non lost with non rest tuples, but lost when encounter rest

The aim is, from a tuple, to get all non optional (optional or rest) items of the tuple.

Everything works just fine, except for one detail: labels when tuple has rest items.

As those are retrieved for tuple without rest, with rest i loose the label information.

// Common types
type Tuple = ReadonlyArray <unknown>

type Tail <T extends Tuple> =
  T extends [] ? T :
  T extends [any?, ...infer R] ? R : T

type Length <T extends Tuple> = T ['length']

type Last <T extends Tuple> = T [Length <Tail <T>>]

// Tests
type Empty = []                           // target: []
type OnlyReq = [a: 1, b: 2]               // target: [a: 1, b: 2]
type WithOpt = [a: 1, b: 2, c?: 3, d?: 4] // target: [a: 1, b: 2]
type WithRest = [a: 1, b?: 2, ...c: 3 []] // target: [a: 1]

type test1 = StripOptionnals <Empty>     // ok: []
type test2 = StripOptionnals <OnlyReq>   // ok: [a: 1, b: 2]
type test3 = StripOptionnals <WithOpt>   // ok: [a: 1, b: 2]
type test4 = StripOptionnals <WithRest>  // need fix, label lost: [1]

// test4 is losing the label informations

// Type
export type StripOptionnals <T extends Tuple> =
  T extends []
  ? []
  : number extends T ['length']
    ? StripOptionnalsRestRec <T, []>
    : StripOptionnalsRec <T>

// here we gather info for the required part of a tuple that have rest items
// but doing so we loose the labels info
type StripOptionnalsRestRec <T extends Tuple, Req extends Tuple> = // <- need fix
  Partial <T> extends T
  ? Req
  : T extends [infer Head, ...infer Rest]
    ? StripOptionnalsRestRec <Rest, [...Req, Head]>
    : Req

// here all works, we take all non optional items and put them in a the req tuple
// and gather all the rest items in the opt tuple
type StripOptionnalsRec <T extends Tuple> =
  undefined extends Last <T>
  ? T extends [...infer Init, any?]
    ? StripOptionnalsRec <Init>
    : never
  : T

playground link



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source