Builder pattern on steroïds with generics and proxy in Typescript
or How the power of Typescript generics and Javascript proxies can allow developers to get ride of a huge number of bolier plate code lines [1/6]

Search for a command to run...
or How the power of Typescript generics and Javascript proxies can allow developers to get ride of a huge number of bolier plate code lines [1/6]

No comments yet. Be the first to comment.
A journey to build a builder infrastructure class using typescript generics and proxy.
Typescript builder tutorial [2/6]
Here is a list of articles about tech that I found interesting during the months of June, July and August. Enjoy! Craft / Architecting The case for server side tracking Beyond Clean Architecture and Domain Driven Design with Functional Core & Impe...

Here is a list of tech articles that I found interesting during the months of February / March / April / May. Enjoy! Node.js / Typescript Express outperformed by Fastify when it comes to JSON processing Node.js 20 is out with among other things pe...

09 - January's Notes Here is a list of articles about tech that I found interesting during the month of January. Enjoy! Nodejs / Typescript / Javascript A comparison of execution time of operations in web assembly in different engines (spoiler alert...

Here is a list of articles about tech that I have found interesting during the months of November and December. Enjoy! Nodejs / Typescript / Javascript Why not having specific version declared for dependencies in package.json can be a bad idea (get ...

Here is a list of articles about tech that I have found interesting during the months of September and Octobre. Enjoy! Nodejs / Typescript / Javascript wasmtime a performant web assembly engine reach 1.0 node.js 18 has a watch mode (no more need of ...

Using an hexagonal or clean architecture is a good way to have a back-end centerred on the business value provided by the application it serves while making it robust on technological changes & evolutions
The business entities are at the core of this architecture. Those entities reflect the different concepts that are manipulated by the back-end of the application. As such another common good practice is to have builders classes to create those entities. As their name indicates, those builder classes follow the Builder Design Pattern.
When you application grows, the number of your business entities can grows quite quickly. As such having a common infrastructure for all those builders of business entities make the creation process less cumbersome.
Using
typescriptand the power of generics, we will see how one can create a base class providing a lot of type checking feature at build time and runtime compatibility that removes the needs of code duplication.
The main goal of this group articles is to showcase some of the latest typescript feature will providing a useful helper that you can use in your projets.
Imagine I want to create an App for storing cooking recipes. I will start simple with at 2 business entities : one that represents a recipe and another one that represents an ingredient of the recipe.
A ingredient will have some properties such as its kind, its amount in weight and a name.
A recipe will have some properties too : a difficulty, a list of ingredients and a name.
I will need also builders for those two entities in order to conveniently build each one of those entities.
In typescript, this translate into code with :
export default class IngredientBE {
public kind: EKind
public weightInKg?: string
public name: string
}
export enum EKind {
Liquid = 0,
Vegetable = 1,
Fruit = 2,
Meat = 3,
Condiment = 4,
Other = 5,
}
export default class Recipe {
public ingredients: Ingredient[]
public difficulty: EDifficulty
public name: string
}
export enum EDifficulty{
Easy = 0,
Medium = 1,
Hard = 2
}
import Ingredient, { EKind } from 'src/useCases/business/entities/Ingredient'
export default class IngredientBuilder {
private builtEntity: Ingredient
constructor() {
this.builtEntity = new Ingredient()
}
public static anIngredient() {
return new IngredientBuilder(Ingredient)
}
public withWeightInGrams(weightInGrams?: number) {
this.builtEntity.weightInGrams = weightInGrams
return this
}
public withKind(kind: EKind) {
this.builtEntity.kind = kind
return this
}
public withName(name: string) {
this.builtEntity.name = name
return this
}
public build(): Ingredient {
const returnedObj = this.builtEntity
this.builtEntity = new Ingredient()
return returnedObj
}
}
import Ingredient from 'src/useCases/business/entities/Ingredient'
import Recipe, { EDifficulty } from 'src/useCases/business/entities/Recipe'
export default class RecipeBuilder {
private builtEntity: Recipe
constructor() {
this.builtEntity = new Recipe()
}
public static anRecipe() {
return new RecipeBuilder(Recipe)
}
public withDifficulty(difficulty: EDifficulty) {
this.builtEntity.difficulty = difficulty
return this
}
public withName(name: string) {
this.builtEntity.name = name
return this
}
public withIngredients(ingredients: Ingredient[]) {
this.builtEntity.ingredients = ingredients
return this
}
public build(): Recipe {
const returnedObj = this.builtEntity
this.builtEntity = new Recipe()
return returnedObj
}
}
From this simple data models as a starting point, I will take a very didactic approach to explain the different feature of typescript we can use to dramatically simplify this code.
If you are already familiar with advanced typescript features and just want to see what could be a convenient-to-use builder infrastructure that makes good use of those features, please have a look at this repo : berlingo-ts