In my scenario, I am looking to create a set of filters in the form of an object. I desire to have complete visibility into all available filters and enable auto-completion for them. However, I want the flexibility for any key to be used as long as it follows certain value types. I initially tried using generics and extends to achieve this, which worked partially. Yet, there were instances where the type unification based on extension did not behave as expected. Below is a simplified example illustrating what I tried:
type Filters = { [key: string]: boolean | string[] }
class Filter<T extends Filters> {
constructor(public filter: T) {}
}
const filter = new Filter({ foo: false, bar: [] })
console.log(filter.filter.foo) // Expected boolean instead of false
for (const item of filter.filter.bar) {
item.includes("x") // Error: Property 'includes' does not exist on type 'never'
}
I anticipated that it would deduce `boolean` for `foo` and `string[]` for `bar`. It seems like the extension process does not merge the types as anticipated. Is there a way to accomplish this in TypeScript? Essentially, having full knowledge of the properties `foo` and `bar` within an instance of `Filter`, while internally treating them as generic types.