Created
August 15, 2019 05:47
-
-
Save dscheerens/66217546121aebcfd31d3d1d8df17de4 to your computer and use it in GitHub Desktop.
Builder pattern applied to InjectionToken factory functions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ======================================== | |
// 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