Reputation: 832
I have a Table component with props like this:
type TableProps<T extends object> = {
columns: Column<T>[];
data: T[];
expandable?: boolean;
};
I'd like to make it so that if the expandable
prop is provided/set to true, it enforces that T extends {details: ReactNode}
instead of T extends object
, as the details node is what I want to render when expanding a row.
Is it possible to use generics in this way?
Upvotes: 1
Views: 893
Reputation: 3662
My suggestion would be to use the ternary conditional typings. You can find more here
And here is how I suggest you to do
type TablePropsCommonProperties<T> = {
columns: Column<T>[];
data: T[];
};
type TablePropsDetails<T extends { details: ReactNode }> = {
expandable: true;
} & TablePropsCommonProperties<T>;
type TablePropsWithoutDetails<T extends object> = {
expandable: false;
} & TablePropsCommonProperties<T>;
type TableProps<T extends object> = T extends { details: ReactNode } ? TablePropsDetails<T> : TablePropsWithoutDetails<T>;
/* Valid */
const validWithDetails: TableProps<{ details: ReactNode }> = {
expandable: true,
columns: ['test'],
data: [{ details: <></> }]
}
/* Not Valid, expandable can't be true if details is not provided */
const notValidDithDetails: TableProps<{ prop: string }> = {
expandable: true,
columns: ['test'],
data: [{ prop: 'my prop' }]
}
Hope that it will help you 🚀
Upvotes: 3