I'm trying create function, that allows me specify some objects that extend type Record<string, Record<string, number>>
) and defaults values for some of the properties for some of the objects.
For example, for given inputs I need to construct specified types that will be later used in 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" }
Basically, if for given object I specify default values for some properties, I want to make this properties optional in the resulting type.
The main problem is that I can't get typescript to narrow inferred type for the second argument(note that I'm not trying to generate resulting type yet, just trying to infer input type correctly to be able 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 example code does not compile because Defaults
is being inferred as [{test: "a" | "b" }]
instead of [{}]
It is heavily inspired by this anwer
I assume I'm making some simple mistake in the Defaults
type but can't get it to work.