Seeking assistance in creating a function that allows for specifying objects which extend the type
Record<string, Record<string, number>>
, along with default values for certain properties within those objects.
For instance, given specific inputs, I need to define types that will later be used in the return value:
[ { obj: { test: { a: 1, b: 2 } }, defaults: {} } ] ---> { test: "a" | "b" }
[ { obj: { test: { a: 1, b: 2 } }, defaults: { test: "b" } } ] ---> { test?: "a" | "b" }
[
{ obj: { test: { a: 1, b: 2 } }, defaults: {} },
{ obj: { test2: { a: 2, d: 5 } }, defaults: { test2: "a" } }
] ---> { test: "a" | "b", test2?: "a" | "d" }
Essentially, if default values are specified for certain properties within an object, those properties should become optional in the resulting type.
The challenge lies in getting TypeScript to accurately infer the type for the second argument. The goal is to correctly infer the input type in order to construct it later:
type Idx<T, K> = K extends keyof T ? T[K] : never
const g = <
Objs extends Record<string, Record<string, number>>[],
Defaults extends { [I in keyof Objs]: { [K in keyof Objs[I]]: keyof Objs[I][K] } }
>(...props:
{ [I in keyof Objs]: { obj: Objs[I], defaults: Idx<Defaults, I> } } &
{ [I in keyof Defaults]: { obj: Idx<Objs, I>, defaults: Defaults[I] } }
) => {}
g({
obj: { test: { a: 1, b:2 } },
defaults: { }
})
This piece of code does not compile as expected because Defaults
is inferred as
[{test: "a" | "b" }]
rather than [{}]
. It draws inspiration from this answer.
It seems there may be a simple error in defining the Defaults
type, but I'm struggling to resolve it.