title: Javascript - Filter result from function that can return Promise boolean OR boolean
body: <p>I wonder if someone ever had this issue before.</p>
  <p>Before I had an EventHandler that would look like this:</p>
  <pre><code>export interface EventHandler {
    name: string;
    canHandleEvent(event: EventEntity): boolean;
    handleEvent(event: EventEntity): Promise&lt;void&gt;;
  }
  </code></pre>
  <p>And my filter function would work normally, also my tests were passing - where I was filtering the events using:</p>
  <pre><code>messages.forEach(message =&gt; {
        const event: EventEntity = JSON.parse(message.Body);
        this.handlers
          .filter(handler =&gt; handler.canHandleEvent(event)) // WORKED WELL
          .forEach(handler =&gt; {
             // LOGIC
          });
  </code></pre>
  <p>Currently, we had to change the <code>canHandleEvent</code> to either Boolean or Promise. Since we had some promises to be resolved and identify whether the event can be handle or not.</p>
  <pre><code>export interface EventHandler {
    // ...
    canHandleEvent(event: EventEntity): boolean | Promise&lt;boolean&gt;;
  }
  </code></pre>
  <p>So, in order to solve it, I used <code>Promise.resolve</code> and <code>Promise.all</code>. No luck:</p>
  <pre><code>messages.forEach(async message =&gt; {
        const event: EventEntity = JSON.parse(message.Body);
        const handlersResolved = await Promise.all(this.handlers);
  
        handlersResolved
          .filter(handler =&gt; handler.canHandleEvent(event))
          .forEach(handler =&gt; {
  </code></pre>
  <p>Now, my tests pass for the Promise <code>canHandleEvent</code>, but they are failing for the events passed that is <code>boolean</code>. They look like this:</p>
  <pre><code>class HandlerB implements EventHandler {
    name = HandlerB.name;
    numRuns = 0;
  
    canHandleEvent(event: EventEntity): boolean {
      console.log('event', event)
      return event.eventType === EventType.ONE_EVENT || event.eventType === EventType.SECOND_EVENT;
    }
    async handleEvent(event: EventEntity): Promise&lt;void&gt; {
      return new Promise(resolve =&gt; {
        setTimeout(() =&gt; {
          this.numRuns += 1;
          resolve();
        }, 25);
      });
    }
  }
  </code></pre>
  <p>And my test that are now failing and before was passing are:</p>
  <pre><code>    it('Should process handlers that match, including canHandleEvent that returns Promise&lt;boolean&gt; TRUE', async () =&gt; {
        setHandlers([handlerA, handlerB, handlerC]);
  
        const event = await createEvent(EventType.SECOND_EVENT);
        await sleep(1000);
  
        expect(handlerA.numRuns, 'handleA').to.eql(0);
        expect(handlerB.numRuns, 'handleB').to.eql(1);
        expect(handlerC.numRuns, 'handleC').to.eql(1); // handlerC is Promise&lt;boolean&gt;, it works fine
        expect(errorHandler.numRuns).to.eql(0);
  
        handlerC.numRuns = 0;
      });
  
      it('Should allow handlers to pass even if one has an error', async () =&gt; {
        setHandlers([handlerA, handlerB, errorHandler]);
  
        const event = await createEvent(EventType.USER_REGISTRATION_STATUS);
        await sleep(1000);
  
        expect(handlerA.numRuns, 'handlerA').to.eql(1);
        expect(handlerB.numRuns, 'handlerB').to.eql(1);
        expect(errorHandler.numRuns, 'errorHandler').to.eql(1);
      });
  
  </code></pre>
  <p>Any thoughts on how to solve this? I've tried to identify whether is promise or boolean before inside the <code>.filter</code> but still no luck:</p>
  <pre><code>      this.handlers
          .filter(async handler =&gt;  {
            if(typeof handler.canHandleEvent(event).then == 'function') {
              const result = await Promise.resolve(handler.canHandleEvent(event))
              console.log('IS PROMISE!!', result);
              return result
            }
            console.log('IT IS NOT PROMISE', handler.canHandleEvent(event))
            return handler.canHandleEvent(event)
          })
  </code></pre>