one way can be to create an interface for Event with different type a, b or c
you can create an interface that will say your elements property can have one instance of each type
interface EventFilter {
  elements: [EventA?, EventB?, EventC?];
}
The limitation of this solution is that element should be added in the order defined in EventFilter
interface Event {
  type: 'a' | 'b' | 'c';
  value: string;
}
interface EventA extends Event {
  type: 'a';
}
interface EventB extends Event {
  type: 'b';
}
interface EventC extends Event {
  type: 'c';
}
interface EventFilter {
  elements: [EventA?, EventB?, EventC?];
}
const app: EventFilter = {
  elements: [ 
    { type: 'a', value: '1' },
    { type: 'b', value: '1' } 
  ],
}
unfortunately, you will have to list all authorised combine to be able to have a flexible array with element in any order
interface EventFilter {
  elements: [EventA?, EventB?, EventC?] | [EventA?, EventC?, EventB?] 
            | [EventB?, EventA?, EventC?] | [EventB?, EventC?, EventA?]
            | [EventC?, EventA?, EventB?] | [EventC?, EventB?, EventA?];
}
const app: EventFilter = {
  elements: [ 
    { type: 'c', value: '1' },
    { type: 'a', value: '1' },
  ],
}