I’m having a bit of trouble figuring out how to handle generic types when receiving component properties in Typescript and React.
For example, here I am trying to make sure that the type of options
in the columns
property of the SubComponent
component is inherited from the generic type OptionsAB
of the object passed to optionSet
: PropertiesAB
.
Here the code I’m testing
interface OptionSet<T> {
options: T[];
}
interface SubComponentProps<TFilter = unknown> {
columns: {
optionSet: OptionSet<TFilter>;
options: TFilter;
}[];
}
export function SubComponent<TFilter = unknown>(_: SubComponentProps<TFilter>) {
return null;
}
interface OptionsAB {
a: string;
b: string;
}
interface OptionsCS {
c: string;
s: string;
}
const PropertiesAB: OptionSet<OptionsAB> = { options: [] };
const PropertiesCS: OptionSet<OptionsCS> = { options: [] };
export const MainComponent = () => {
return (
<SubComponent
columns={[
{ optionSet: PropertiesAB, options: { a: "b", b: "s" } }, // This should work
{ optionSet: PropertiesAB, options: { a: "b" } }, // This should throw error
{ optionSet: PropertiesCS, options: { a: "b" } }, // This should throw error
]}
/>
);
};
But the type of options
is always unknown
. And the type of optionSet
is also read as OptionSet<unknown>
and not OptionSet<OptionsAB>
Where am I going wrong?
Thanks
2
Answers
The main cause of your problem, is that typescript generic will infer type from the most "shallow" generic.. in your case:
in new typescript there will be new
NoInfer
helper type and it should work…Playground
currently you can use some custom helper type like:
Playground
Create a NoInfer helper type in TypeScript. This type utilizes conditional types to prevent TypeScript from inferring the type too early. Here’s how you can integrate NoInfer into your code: