1

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

zedryas
  • 718
  • 6
  • 19
  • Is it possible to minimize ? Anyway, you can find related answers [here](https://stackoverflow.com/questions/69973072/how-can-you-ensure-that-tuple-element-labels-are-preserved) and [here](https://stackoverflow.com/questions/64189351/type-level-operations-for-labelled-tuple/64194372#64194372) – captain-yossarian from Ukraine Feb 22 '22 at 14:17
  • 2
    The label are in most case preserved with what is given, the only issue is when a tuple has rest `[1, 2, ...3 []]` in which case the code above loose the labels for the required part of the tuple - I've got the impression that the question linked do not ask that but only for level (non rest). I've tried to simplify further the code thanks for taking the time to read it @captain-yossarian ;) – zedryas Feb 22 '22 at 14:30
  • @captain-yossarian i've stripped a few things from the code not sure if I can go further thou :/ – zedryas Feb 22 '22 at 14:34
  • @zedryas I think what would solve your issue is if we could extract the first element of a tuple in another tuple, preserving the label. But this does not seem to work if the tuple has a rest element: https://www.typescriptlang.org/play?strict=false#code/C4TwDgpgBAGlC8UDaBDAXFAjAGgEYYCZsoBjDAZiQF0qoIAPYCAOwBMBnZAOh4EtmAZhABOUAKpRsRKJRpQA-OIzMIANxFQA9JuTosVAFChIsAgl0Yc+KNJ5cyM6rQZM2nJHf5DREqcTuytIpiymoa2lAArswA1swA9gDuzNQGBkA – Titian Cernicova-Dragomir Feb 22 '22 at 14:56
  • yep that the isssue I encounter and that's why I nee to use `StripOptionnalsRestRec` to gather when the tuple has rest :/ – zedryas Feb 22 '22 at 15:07
  • 1
    Looks like the `LabeledSingleton` thing I do [here](https://stackoverflow.com/a/67260129/2887218) runs into the same issue with rest elements so I don't have much insight here. Maybe people have seen it in GitHub? – jcalz Feb 22 '22 at 17:00
  • 1
    https://github.com/microsoft/TypeScript/issues/43020 and https://github.com/microsoft/TypeScript/issues/39941 seem relevant but not promising (i.e., they don't seem particularly interested in expending a lot of effort to preserve names in all cases) – jcalz Feb 22 '22 at 23:03
  • @jcalz do you reckon it would make sens to have a generic type `Tuple` in the typescript system (like we have `Array`) ? this type would required label etc and I fill it might be a good addition for whenever we want tot type functions and functions transformers ? worth writing a PR ? – zedryas Feb 25 '22 at 13:04
  • I don't really see how that would improve things, but without a detailed proposal it's hard to know one way or the other. It would be nice to have some more programmatic control over tuple labels, but I don't know that we need a new type for it. – jcalz Feb 25 '22 at 19:12

0 Answers0