The following code doesn't work, as the converter function by Typescript should expect a parameter typed Filters
. How can we make this work, so that the argument is based on the type of the key
of the object?
type Filter1 = {
type: 'filter1',
value1: number
}
type Filter2 = {
type: 'filter2',
value2: number;
}
type Filters = Filter1 | Filter2;
const converter: Record<Filters['type'], (filter: Filters) => string> => {
// I'd want:
// filter1: (filter: Filter1) => {
filter1: (filter: Filter) => {
return (filter as Filter1).value1.toString();
},
// filter2: (filter: Filter2) => {
filter2: (filter: Filter) => {
return (filter as Filter2).value2.toString();
},
}
You don't want to use the Record<K, V>
type, because the keys and value types of Record
are independent of each other. If you want the property type at a key to depend on the key, then you need a more general mapped type.
In particular you seem to be looking for a key remapped type where you iterate over the elements of the Filter
union and use its type
property as the key:
type Converter = { [T in Filters as T['type']]: (filter: T) => string }
/* type Converter = {
filter1: (filter: Filter1) => string;
filter2: (filter: Filter2) => string;
} */
const converter: Converter = {
filter1: filter => {
return filter.value1.toString();
},
filter2: filter => {
return filter.value2.toString();
},
}
That now behaves as desired, and note that the filter
callback parameters are contextually types by Converter
so you don't have to annotate them.