Skip to content

Instantly share code, notes, and snippets.

@dscheerens
Created August 15, 2019 05:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dscheerens/66217546121aebcfd31d3d1d8df17de4 to your computer and use it in GitHub Desktop.
Save dscheerens/66217546121aebcfd31d3d1d8df17de4 to your computer and use it in GitHub Desktop.
Builder pattern applied to InjectionToken factory functions
// ========================================
// app-module.ts
// ========================================
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { NumbersModule } from './numbers';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
NumbersModule
],
bootstrap: [AppComponent]
})
export class AppModule { }
// ========================================
// numbers.ts
// ========================================
import { InjectionToken, NgModule } from '@angular/core';
export const TWO = new InjectionToken<number>('TWO');
export const SEVEN = new InjectionToken<number>('SEVEN');
export const EIGHT = new InjectionToken<number>('EIGHT');
export const NINE = new InjectionToken<number>('NINE');
@NgModule({
providers: [
{ provide: TWO, useValue: 2 },
{ provide: SEVEN, useValue: 7 },
{ provide: EIGHT, useFactory: () => 2 + 2 * 2 + 2 },
{ provide: NINE, useFactory: (two: number, seven: number) => two + seven, deps: [TWO, SEVEN] }
]
})
export class NumbersModule {
}
// ========================================
// app.component.ts
// ========================================
import { Component, Inject, InjectionToken, inject } from '@angular/core';
import { SEVEN, EIGHT, NINE } from './numbers';
export class Foo {
public readonly data = { a: 1, b: 2, c: 3 };
}
export const SIX = new InjectionToken<number>('SIX', { providedIn: 'root', factory: () => 6 })
type FooFactory = () => Foo;
type FooBuilderFactory = FooFactory & {
a(a: InjectionToken<number>): FooBuilderFactory;
b(b: InjectionToken<number>): FooBuilderFactory;
c(c: InjectionToken<number>): FooBuilderFactory;
}
export function fooFactoryFactory(a: InjectionToken<number>, b: InjectionToken<number>, c: InjectionToken<number>): FooBuilderFactory {
const foo = new Foo();
const injectionInputs = { a, b, c };
const factory = (() => {
foo.data.a = inject(injectionInputs.a);
foo.data.b = inject(injectionInputs.b);
foo.data.c = inject(injectionInputs.a) * inject(injectionInputs.b) * inject(injectionInputs.c);
return foo;
}) as FooBuilderFactory;
factory.a = (_a: InjectionToken<number>) => { injectionInputs.a = _a; return factory; }
factory.b = (_b: InjectionToken<number>) => { injectionInputs.b = _b; return factory; }
factory.c = (_c: InjectionToken<number>) => { injectionInputs.c = _c; return factory; }
return factory;
}
export const FOO = new InjectionToken<Foo>('FOO', {
providedIn: 'root',
factory: fooFactoryFactory(SEVEN, SIX, EIGHT).a(EIGHT).c(NINE)
});
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'injection-test';
constructor(@Inject(FOO) foo: Foo) {
console.log('foo =', foo);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment