Skip to content

ObservableV2 template is too permissive #83

@djrenren

Description

@djrenren

Describe the bug

The ObservableV2 class allows the specification of a type which defines the set of events and callbacks, but the template is overly permissive. Namely, the EVENT parameter can constrain the callbacks such that every callback must return a value. This possibility makes it very difficult to write well-typed abstractions over ObservableV2 (they must handle the case where EVENTS has been instantiated this way).

To Reproduce

Here's a small example of this in typescript:

function foo() {
    let x = new ObservableV2<{"hi": () => number}>();
    x.on('hi', () => {}); // ERROR HERE
}

Which results in the error:

Argument of type '() => void' is not assignable to parameter of type '() => number'.
  Type 'void' is not assignable to type 'number'.ts(2345)

Expected behavior
ObservableV2 should always allow callbacks that return void.

Additional context
I ran into this problem while trying to write a utility function called waitUntil that runs a test on all emitted events and resolves a promise when it successfully passes the test. The untyped form is basically:

const waitUntil = (observable, event, test) => Promise.new(resolve => {
    function cb(..args) {
        if (test(...args)) {
            observable.off(event, cb);
            resolve(args);
        }
    }
    
    observable.on(event, cb);
});

This lets me write nice little functions like:

const waitUntilConnected = (client) => 
    waitUntil(client, "update", status => (status === "connected"));

Unfortunately it's impossible (or at least beyond me) to make the function cb inside waitUntil typecheck because the observable could require that callbacks for this event return a value.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions