Skip to content

Instantly share code, notes, and snippets.

@dscheerens
Created October 21, 2020 19:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dscheerens/d6ef4c2f384017f3f98ebb6fc181d680 to your computer and use it in GitHub Desktop.
Save dscheerens/d6ef4c2f384017f3f98ebb6fc181d680 to your computer and use it in GitHub Desktop.
Initializer decorator for Angular components (fully type-safe!)
import { Subscription } from 'rxjs';
const GLOBAL_COMPONENT_SUBSCRIPTIONS = new WeakMap<any, Set<Subscription>>();
export function NgInit<
TargetType extends { constructor: Function, ngOnInit?(): void, ngOnDestroy?(): void },
PropertyKey extends string,
PropertyContainer extends { [k in PropertyKey]: () => (void | Subscription) },
FunctionType extends PropertyContainer[PropertyKey]
>(
target: TargetType & PropertyContainer,
propertyKey: PropertyKey,
_descriptor: TypedPropertyDescriptor<FunctionType>
) {
const originalOnInit = target.ngOnInit;
const originalOnDestroy = target.ngOnDestroy;
target.ngOnInit = function(this: PropertyContainer) {
if (originalOnInit) {
originalOnInit.call(this);
}
const result = this[propertyKey].call(this);
if (result instanceof Subscription) {
let componentSubscriptions = GLOBAL_COMPONENT_SUBSCRIPTIONS.get(this);
if (!componentSubscriptions) {
componentSubscriptions = new Set<Subscription>();
GLOBAL_COMPONENT_SUBSCRIPTIONS.set(this, componentSubscriptions);
}
componentSubscriptions.add(result);
}
};
target.ngOnDestroy = function(this: PropertyContainer) {
if (originalOnDestroy) {
originalOnDestroy.call(this);
}
const componentSubscriptions = GLOBAL_COMPONENT_SUBSCRIPTIONS.get(this);
GLOBAL_COMPONENT_SUBSCRIPTIONS.delete(this);
componentSubscriptions?.forEach((subscription) => subscription.unsubscribe());
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment