If I am understanding your requirements correctly, botVariables
could be anything, but the botVariables
and the botCommands
that we provide to the TestComponent
need to match each other. That is, the arguments of the botResponse
function in the botCommands
are the same type as the botVariables
prop.
In order to do this, we make the BotCommand
interface generic, where the type T
represents the type of the botResponse
variables.
interface BotCommand<T> {
command: string;
botResponse(botVariables: T): string;
}
Our TestComponentProps
are also generic, and we apply the same T
to the botVariables
as to the botCommands
.
interface TestComponentProps<T> {
botVariables: T;
botCommands: BotCommand<T>[];
}
This means the component is generic as well.
export default function TestComponent<T>(props: TestComponentProps<T>) {...}
There is no problem creating a response from the passed variables, since both props
share the same T
.
export default function TestComponent<T>({ botVariables, botCommands }: TestComponentProps<T>) {
return (
<div>
<h1>Bot Output</h1>
{botCommands.map(command => (
<div>
<div>Bot recieved command {command.command}</div>
<div>Bot responded {command.botResponse(botVariables)}</div>
</div>
))}
</div>
);
}
You don't need to explicitly declare the generic T
when you use the TestComponent
because it can be inferred from the botVariables
prop. If the botCommands
don't match, typescript will complain.
In this example:
function Main() {
return (
<TestComponent
botVariables={{
tasks: ["first"],
groups: ["something"]
}}
botCommands={[{
command: "-help",
botResponse(botVariables) {
return botVariables.tasks[0]
}
}]}
/>
);
}
The inferred signature for the botResponse
function is complete and correct:
(method) BotCommand<{ tasks: string[]; groups: string[]; }>.botResponse(botVariables: {
tasks: string[];
groups: string[];
}): string
In order to get proper inference, I had to use ["first"]
instead of an empty array because empty arrays are typed as never[]
but we want string[]
. You can use an empty array, but you would have to explicitly set the type for it.
Playground Link