gvergnaud / hotscript

A library of composable functions for the type-level! Transform your TypeScript types in any way you want using functions you already know.
3.38k stars 57 forks source link

Unions.ToTuple not working with Match #111

Closed iSplasher closed 8 months ago

iSplasher commented 8 months ago

Hi, is this a bug?

type Bug<U extends "a" | "b" | "" = ""> = Call< Tuples.Map<Match<[
  Match.With<"a", { a: true }>,
  Match.With<"b", { b: true }>,
  Match.With<any, Identity>,
]>>, Unions.ToTuple<U>>

type test1 = Bug<"a"> // every arg yields never

// but this half works

type HalfWorks<U extends "a" | "b" | "" = ""> = Call< Tuples.Map<Match<[
  Match.With<"a", { a: true }>,
  Match.With<"b", { b: true }>,
  Match.With<any, Identity>,
]>>, [U]>

type test2 = HalfWorks<"a"> // [{ a: true; }]
type test3 = HalfWorks<"a" | "b"> // ["a" | "b"]

Did I miss anything?

Edit: I realize there's a workaround:

Call< Unions.Map<Match<[
  Match.With<"a", { a: true }>,
  Match.With<"b", { b: true }>,
  Match.With<any, Identity>,
]>>, U>

However, I'm curious why the above bug example doesn't work.

ecyrbe commented 8 months ago

The second parameter you passed is a lazy Hotscript function, you need to call it (also use $ instead of Call, it's a short alias and it's this way easier to read) :

type Works<U extends "a" | "b" | "" = ""> = $< Tuples.Map, Match<[
  Match.With<"a", { a: true }>,
  Match.With<"b", { b: true }>,
  Match.With<any, Identity>,
]>, $<Unions.ToTuple,U>>

Think, $ as a way to call Hotscript generic, so :

type Test = $<HotscriptLazyFunc, Param1, Param2>;

is equivalent in standard generics to :

type Test = GenericFunc< Param1, Param2>;