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', { ... }], ] */
Preview:
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