I’ve been fiddling with some transformation of arguments of a function via a recursive type, have some issue to make the type work, I made same simplified example to highlight the issue, together with examples using mapped type (for this toy example mapped type would be enough): Playground
First I just create Transform functions using both mapped types and recursive type, with test data and tests to ensure that these return the same result.
type TestItems = [string, number, string, boolean]
export type MappedTransform<UnionWith, Items extends any[]>
= { [I in keyof Items]: Items[I] | UnionWith }
type RecursiveTransform<UnionWith, Items extends any[]>
= Items extends [infer Head, ...infer Tail]
? [Head | UnionWith, ...RecursiveTransform<UnionWith, Tail>]
: [];
type mappedTypes = MappedTransform<undefined, TestItems>
type recursiveTypes = RecursiveTransform<undefined, TestItems>
Then I have a function that uses transform via mapped type. I suppose that UnionWith type gets plugged in as first type argument wheres second argument is filled with tuple type with types of arguments of the function. This creates a correct type.
export const fnWithMappedType = <UnionWith extends any, Args extends any[]>
(data: UnionWith, ...args: MappedTransform<UnionWith, Args>) => {}
fnWithMappedType(undefined, "first", 42, true)
Next is the problem part: The types plugged into recursive type transformer the same way as above, into type that behaves same way in isolation in test examples behaves differently, and results in empty tuple, so that function accepts only the very first parameter unlike all four in previous example.
export const fnWithRecursiveType = <UnionWith extends any, Args extends any[]>
(data: UnionWith, ...args: RecursiveTransform<UnionWith, Args>) => {}
fnWithRecursiveType(undefined, "first", 42, true)
Is there some hidden gotcha or did I miss something, can this be solved so that arguments may be transformed by recursive type?