I am adding one Select component that has the following structure.
type Option = {
value: string | number
label: string;
icon?: string
}
type SelectProps = {
labelKey?: string;
iconKey?: string;
valueKe?: string;
options: Option[]
}
function Select({
labelKey = 'label',
iconKey = 'icon',
valueKey= 'value',
groupBy = 'groupBy',
options// need to type Option
}: SelectProps) {
// some logic to render options
// options.map(option => (<li key={option[valueKey]}>{option[labelKey]}</li>))
}
Here, options is an array of options and I am trying to give flexibility to users to provide keys to use for labels, icons etc so the user doesn't need to map data all the time.
For now, the Option type has hardcode keys like label, value, icon but I want to create this type based on values passed to labelKey, valueKey, iconKey etc.
For example, if a user passes the labelKey="name" prop then the Option type should allow the following data:
[ {
name: 'Product',
value: 'product',
icon: 'product'
}]
So far I have tried the following implementation but it sets all keys' types to string.
type OptionKeys = {labelKey: string, valueKey: string, iconKey: string}
type Option<T extends OptionKeys> = {
[label in T["labelKey" | "valueKey" | "iconKey"]]: string // all the types are string
}
type SelectProps<T extends OptionKeys = {
labelKey: 'label',
valueKey: 'value',
iconKey: 'icon'
}> = {
labelKey?: string
valueKey?: string;
iconKey?: string;
options: Option<T>[]
}
Here, the Option's keys have value of type string but I want to define type based on key. For example, if the key is labelKey, I want its value to be number | string etc.
One option, I see here is to accept OptionType from outside by making the Select component generic but in that case, I need to refactor my component and want to avoid this refactoring at the moment.
How can I update my type to handle this scenario?