/** * */ export interface IDisposable { dispose(): void; } export interface ISubscription { unsubscribe(): void; } export function isDisposable(value: any): value is IDisposable { return !!value.dispose; } export function isSubscription(value: any): value is ISubscription { return !!value.unsubscribe; } export function canBeDisposed(value: any): value is IDisposableOrSubscription { return !!(value.dispose || value.unsubscribe) || typeof value === 'function'; } export type IDisposableOrSubscription = IDisposable | ISubscription | (() => void); // eslint-disable-next-line prefer-const let empty: Disposable; export class Disposable implements IDisposable, ISubscription { public static get empty() { return empty; } /* tslint:disable-next-line:no-reserved-keywords no-any */ public static of(value: any) { if (!value) { return empty; } if (value.dispose) { return value; } return new Disposable(value); } public static create(value: IDisposableOrSubscription): IDisposable & ISubscription; public static create(action: () => void): IDisposable & ISubscription; public static create(action: IDisposableOrSubscription | (() => void)) { return new Disposable(action); } private _action: () => void = () => {}; private _isDisposed = false; constructor(value: IDisposableOrSubscription); /* tslint:disable-next-line:no-any */ constructor(value: any) { if (!value) { return empty; } if (typeof value === 'function') { this._action = value; } else if (value.unsubscribe) { this._action = () => (value).unsubscribe(); } else if (value.dispose) { this._action = () => (value).dispose(); } } public get isDisposed() { return this._isDisposed; } public dispose() { if (this._isDisposed) return; this._isDisposed = true; this._action(); } public unsubscribe(): void { this.dispose(); } } empty = new Disposable(() => { /* */ });