Add shorthand interfaces for the Backbone.Events methods

This commit is contained in:
Julian Gonggrijp
2019-02-15 02:10:19 +01:00
parent 6202c307db
commit 342615bd7f
2 changed files with 104 additions and 7 deletions

View File

@@ -15,6 +15,50 @@ function test_events() {
object.off();
}
class PubSub implements Backbone.Events {
on: Backbone.Events_On<PubSub>;
off: Backbone.Events_Off<PubSub>;
trigger: Backbone.Events_Trigger<PubSub>;
bind: Backbone.Events_On<PubSub>;
unbind: Backbone.Events_Off<PubSub>;
once: Backbone.Events_On<PubSub>;
listenTo: Backbone.Events_Listen<PubSub>;
listenToOnce: Backbone.Events_Listen<PubSub>;
stopListening: Backbone.Events_Stop<PubSub>;
}
Object.assign(PubSub.prototype, Backbone.Events);
function test_events_shorthands() {
let channel1 = new PubSub();
let channel2 = new PubSub();
let onChange = () => alert('whatever');
channel1.on("alert", (eventName: string) => alert("Triggered " + eventName));
channel1.trigger("alert", "an event");
channel1.once('invalid', () => { }, this);
channel1.once('invalid', () => { });
channel1.once({invalid: () => { }, success: () => { }}, this);
channel1.once({invalid: () => { }, success: () => { }});
channel1.off("change", onChange);
channel1.off("change");
channel1.off(null, onChange);
channel1.off(null, null, this);
channel1.off();
channel2.listenTo(channel1, 'invalid', () => { });
channel2.listenTo(channel1, {invalid: () => { }, success: () => { }});
channel2.listenToOnce(channel1, 'invalid', () => { });
channel2.listenToOnce(channel1, {invalid: () => { }, success: () => { }});
channel2.stopListening(channel1, 'invalid', () => { });
channel2.stopListening(channel1, 'invalid');
channel2.stopListening(channel1);
}
class SettingDefaults extends Backbone.Model {
// 'defaults' could be set in one of the following ways:

View File

@@ -110,13 +110,14 @@ declare namespace Backbone {
}
/**
* Helper to avoid code repetition. Backbone.Events cannot be extended,
* hence a separate abstract class with a different name.
* Both classes and interfaces can extend from this helper class to
* reuse the signatures, but only in type declarations.
* Classes that already extend another base class can still
* `implements Events`, but in this case, unfortunately you have to
* repeat all signatures below.
* Helper to avoid code repetition in type declarations.
* Backbone.Events cannot be extended, hence a separate abstract
* class with a different name. Both classes and interfaces can
* extend from this helper class to reuse the signatures.
*
* For class type declarations that already extend another base
* class, and for actual class definitions, please see the
* EventsMethod* interfaces below.
*/
abstract class EventsMixin implements Events {
on(eventName: string, callback: EventHandler, context?: any): this;
@@ -139,6 +140,58 @@ declare namespace Backbone {
export const Events: Events;
interface Events extends EventsMixin { }
/**
* Helper shorthands for classes that implement the Events interface.
* Define your class like this:
*
* import {
* Events,
* Events_On,
* Events_Off,
* Events_Trigger,
* Events_Listen,
* Events_Stop,
* } from 'backbone';
*
* class YourClass implements Events {
* on: Events_On<YourClass>;
* off: Events_Off<YourClass>;
* trigger: Events_Trigger<YourClass>;
* bind: Events_On<YourClass>;
* unbind: Events_Off<YourClass>;
*
* once: Events_On<YourClass>;
* listenTo: Events_Listen<YourClass>;
* listenToOnce: Events_Listen<YourClass>;
* stopListening: Events_Stop<YourClass>;
*
* // ... (other methods)
* }
*
* Object.assign(YourClass.prototype, Events); // can also use _.extend
*
* If you are just writing a class type declaration that doesn't already
* extend some other base class, you can use the EventsMixin instead;
* see above.
*/
interface Events_On<BaseT> {
<T extends BaseT>(this: T, eventName: string, callback: EventHandler, context?: any): T;
<T extends BaseT>(this: T, eventMap: EventMap, context?: any): T;
}
interface Events_Off<BaseT> {
<T extends BaseT>(this: T, eventName?: string, callback?: EventHandler, context?: any): T;
}
interface Events_Trigger<BaseT> {
<T extends BaseT>(this: T, eventName: string, ...args: any[]): T;
}
interface Events_Listen<BaseT> {
<T extends BaseT>(this: T, object: any, events: string, callback: EventHandler): T;
<T extends BaseT>(this: T, object: any, eventMap: EventMap): T;
}
interface Events_Stop<BaseT> {
<T extends BaseT>(this: T, object?: any, events?: string, callback?: EventHandler): T;
}
class ModelBase extends EventsMixin {
parse(response: any, options?: any): any;
toJSON(options?: any): any;