interfaces inicializar herencia clases clase typescript

inicializar - interfaces o clases typescript



¿TypeScript admite eventos en las clases? (6)

¿Qué tal este evento simplificado para ser utilizado como una propiedad? Tipeo más fuerte de la clase propietaria y sin requisito de herencia:

interface ILiteEvent<T> { on(handler: { (data?: T): void }) : void; off(handler: { (data?: T): void }) : void; } class LiteEvent<T> implements ILiteEvent<T> { private handlers: { (data?: T): void; }[] = []; public on(handler: { (data?: T): void }) : void { this.handlers.push(handler); } public off(handler: { (data?: T): void }) : void { this.handlers = this.handlers.filter(h => h !== handler); } public trigger(data?: T) { this.handlers.slice(0).forEach(h => h(data)); } public expose() : ILiteEvent<T> { return this; } }

usado como tal:

class Security{ private readonly onLogin = new LiteEvent<string>(); private readonly onLogout = new LiteEvent<void>(); public get LoggedIn() { return this.onLogin.expose(); } public get LoggedOut() { return this.onLogout.expose(); } // ... onLogin.trigger(''bob''); } function Init() { var security = new Security(); var loggedOut = () => { /* ... */ } security.LoggedIn.on((username?) => { /* ... */ }); security.LoggedOut.on(loggedOut); // ... security.LoggedOut.off(loggedOut); }

Mejoras?

Una idea para esto

Me pregunto si en TypeScript puedes definir eventos personalizados en tus clases o interfaces.

¿A qué se parecería?


Creo que estás preguntando si una instancia de clase puede implementar addEventListener () y dispatchEvent () como un elemento DOM. Si la clase no es un nodo DOM, entonces tendría que escribir su propio bus de eventos. Definiría una interfaz para una clase que puede publicar eventos, luego implementaría la interfaz en sus clases. Aquí hay un ejemplo ingenuo;

interface IEventDispatcher{ // maintain a list of listeners addEventListener(theEvent:string, theHandler:any); // remove a listener removeEventListener(theEvent:string, theHandler:any); // remove all listeners removeAllListeners(theEvent:string); // dispatch event to all listeners dispatchAll(theEvent:string); // send event to a handler dispatchEvent(theEvent:string, theHandler:any); } class EventDispatcher implement IEventDispatcher { private _eventHandlers = {}; // maintain a list of listeners public addEventListener(theEvent:string, theHandler:any) { this._eventHandlers[theEvent] = this._eventHandlers[theEvent] || []; this._eventHandlers[theEvent].push(theHandler); } // remove a listener removeEventListener(theEvent:string, theHandler:any) { // TODO } // remove all listeners removeAllListeners(theEvent:string) { // TODO } // dispatch event to all listeners dispatchAll(theEvent:string) { var theHandlers = this._eventHandlers[theEvent]; if(theHandlers) { for(var i = 0; i < theHandlers.length; i += 1) { dispatchEvent(theEvent, theHandlers[i]); } } } // send event to a handler dispatchEvent(theEvent:string, theHandler:any) { theHandler(theEvent); } }


El evento Strongly Typed Events for TypeScript (versión 0.3 ) implementa 3 tipos de eventos: IEvent<TSender, TArgs> , ISimpleEvent<TArgs> e ISignal . Esto facilita el uso del tipo de evento adecuado para su proyecto. También oculta el método de envío de su evento, como lo haría una buena ocultación de la información.

Tipos de eventos / Interfaces : las definiciones de los eventos:

interface IEventHandler<TSender, TArgs> { (sender: TSender, args: TArgs): void } interface ISimpleEventHandler<TArgs> { (args: TArgs): void } interface ISignalHandler { (): void; }

Ejemplo : este ejemplo muestra cómo se pueden implementar los 3 tipos de eventos usando un reloj de tiempo:

class Clock { //implement events as private dispatchers: private _onTick = new SignalDispatcher(); private _onSequenceTick = new SimpleEventDispatcher<number>(); private _onClockTick = new EventDispatcher<Clock, number>(); private _ticks: number = 0; constructor(public name: string, timeout: number) { window.setInterval( () => { this.Tick(); }, timeout); } private Tick(): void { this._ticks += 1; //trigger event by calling the dispatch method and provide data this._onTick.dispatch(); this._onSequenceTick.dispatch(this._ticks); this._onClockTick.dispatch(this, this._ticks); } //expose the events through the interfaces - use the asEvent //method to prevent exposure of the dispatch method: public get onTick(): ISignal { return this._onTick.asEvent(); } public get onSequenceTick() : ISimpleEvent<number>{ return this._onSequenceTick.asEvent(); } public get onClockTick(): IEvent<Clock, number> { return this._onClockTick.asEvent(); } }

Uso : se puede usar así:

let clock = new Clock(''Smu'', 1000); //log the ticks to the console clock.onTick.subscribe(()=> console.log(''Tick!'')); //log the sequence parameter to the console clock.onSequenceTick.subscribe((s) => console.log(`Sequence: ${s}`)); //log the name of the clock and the tick argument to the console clock.onClockTick.subscribe((c, n) => console.log(`${c.name} ticked ${n} times.`))

Lea más aquí: sobre eventos, despachadores y listas (una explicación general del sistema)

Tutoriales
He escrito algunos tutoriales sobre el tema:


Esta solución le permite escribir directamente los parámetros en la llamada de función en lugar de tener que ajustar todos sus parámetros en un objeto.

interface ISubscription { (...args: any[]): void; } class PubSub<T extends ISubscription> { protected _subscribed : ISubscriptionItem[] = []; protected findSubscription(event : T) : ISubscriptionItem { this._subscribed.forEach( (item : ISubscriptionItem) =>{ if (item.func==event) return item; } ); return null; } public sub(applyObject : any,event : T) { var newItem = this.findSubscription(event); if (!newItem) { newItem = {object : applyObject, func : event }; this._subscribed.push(newItem); this.doChangedEvent(); } } public unsub(event : T) { for ( var i=this._subscribed.length-1 ; i>=0; i--) { if (this._subscribed[i].func==event) this._subscribed.splice(i,1); } this.doChangedEvent(); } protected doPub(...args: any[]) { this._subscribed.forEach((item : ISubscriptionItem)=> { item.func.apply(item.object, args); }) } public get pub() : T { var pubsub=this; var func= (...args: any[]) => { pubsub.doPub(args); } return <T>func; } public get pubAsync() : T { var pubsub=this; var func = (...args: any[]) => { setTimeout( () => { pubsub.doPub(args); }); } return <T>func; } public get count() : number { return this._subscribed.length } }

Uso:

interface ITestEvent { (test : string): void; } var onTestEvent = new PubSub<ITestEvent>(); //subscribe to the event onTestEvent.sub(monitor,(test : string) => {alert("called:"+test)}); //call the event onTestEvent.pub("test1");


Puede usar eventos personalizados en TypeScript. No estoy seguro exactamente de lo que intenta hacer, pero aquí hay un ejemplo:

module Example { export class ClassWithEvents { public div: HTMLElement; constructor (id: string) { this.div = document.getElementById(id); // Create the event var evt = document.createEvent(''Event''); evt.initEvent(''customevent'', true, true); // Create a listener for the event var listener = function (e: Event) { var element = <HTMLElement> e.target; element.innerHTML = ''hello''; } // Attach the listener to the event this.div.addEventListener(''customevent'', listener); // Trigger the event this.div.dispatchEvent(evt); } } }

Si está buscando hacer algo más específico, por favor hágamelo saber.


Si está buscando obtener la verificación de tipo de inteligencia mediante el patrón de emisor estándar, ahora puede hacer lo siguiente:

type DataEventType = "data"; type ErrorEventType = "error"; declare interface IDataStore<TResponse> extends Emitter { on(name: DataEventType, handler : (data: TResponse) => void); on(name: ErrorEventType, handler: (error: any) => void); }