Preview:
type FooFilter<T> = { type: 'Foo', foo: T }
type BarFilter<T> = { type: 'Bar', bar: T }
type Filter = FooFilter<unknown> | BarFilter<unknown>
type FilterShapeBase = [string, Filter][]

type ValueOf<F extends Filter> = 
F extends FooFilter<infer T> ? T
: F extends BarFilter<infer T> ? T
: never

type FilterValues<FilterShape extends FilterShapeBase> = FilterShape extends Array<infer U>
    ? U extends [infer K, infer F] 
        ? K extends string
            ? F extends Filter
                ? { [Key in K]: ValueOf<F> }
                : never
            : never
        : never
    : never

function f<FilterShape extends FilterShapeBase>(filters: FilterShape): FilterValues<FilterShape> {
    const tuples = filters.map(([key, filter]) => filter.type === 'Foo' ? [key, filter.foo] : [key, filter.bar])
    return Object.fromEntries(tuples)
}

/*
HOW TO CONFIGURE THE FILTER FilterShape:

type FilterShape = [
  ['foo_in', StringSearchFilter],
  ['bar_equals', EnumSelectOneFilter<MyEnum>]
]

const filters = [
  ['foo_in', { ... }],
  ['bar_equals', { ... }],
]
*/
downloadDownload PNG downloadDownload JPEG downloadDownload SVG

Tip: You can change the style, width & colours of the snippet with the inspect tool before clicking Download!

Click to optimize width for Twitter