I'm trying to capture the value of a record that is nested in a property. However, I seem to only be able to capture the top-level types in the generic not nested ones.
Here's an example that demonstrating what I'm trying to do:
interface RunConfig<
TContext extends Record<string, any>,
TChildren extends Record<string, RunConfig<any, any>>
> {
context: TContext;
fn: (arg: { context: TContext }) => any;
children: {
[child in keyof TChildren]: RunConfig<
TChildren[child]["context"],
TChildren[child]["children"]
>;
};
}
function run<
TContext extends Record<string, any>,
TChildren extends Record<string, RunConfig<any, any>>
>(config: RunConfig<TContext, TChildren>) {
const { context, fn, children } = config;
fn({ context });
for (const config of Object.values(children)) {
run(config);
}
}
run({
context: {
context: {
key0: "value0",
},
},
fn({ context }) {
// Should be `{ key0: string; }`...and it is! Yay...
console.log("child0", { context });
},
children: {
child1: {
context: {
key1: "value1",
},
fn({ context }) {
// Should be `{ key1: string; }`...but it is `any`. Booo...
console.log("child1", { context });
},
children: {
child11: {
context: {
key11: "value11",
},
fn({ context }) {
console.log("child11", { context });
},
children: {},
},
},
},
child2: {
context: {
key2: "value2",
},
fn({ context }) {
console.log("child2", { context });
},
children: {},
},
},
});
The top level fn correctly infers the context type as { key0: string; } but the child fn inputs are typed as { context: any };
Ultimately, I'd want the children to receive their own context as well as their ancestors' context, but I need to get over this initial hump first.