# Dynamic methods with Typescript

# Introduction

To get rid of the build error we had in the previous article, we will need to make our builder methods "dynamic". To achieve that, we will use one of the powerful feature of typescript, the definition of types.

# Toying with types
We will define the following type : 
```typescript
type BuilderWithTypeMethods<T> = EntityBuilder<T> & {
  [K in keyof T]:
  (value: T[K]) => BuilderWithTypeMethods<T>
}
```

Let's take the time to analyse this type. We see that our type is using :
- The *op1* `&` *op2* operator allows to merge the two types provided as the two operands.
```typescript
type mergedTypes = { x: string } & { y: number } // { x: string, y: number } 
```
-  The `keyof` *op1* operator gets a new `union type` constituting of all the key of the type provided as the right operand.
```typescript
type possibleKeys = { x: string, y: number } // 'x' | 'y'
```
- The *op1* `in` *op2* operator gets an iterator from all the possible types of a the `union type` provided to its right operand an assign it to its left operand. It can only be used in the definition of the key of an `object type` 
```typescript
type keys = 'x' | 'y'
type objectWithStringProperties = {
	[K in keys] : string
} // { x: string, y: string }
```

Knowing all this we can deduce that the `BuilderWithTypeMethods<T>` type is an `EntityBuilderType` for `T` on which for each of the properties of type `T` a method named from the property name which have on parameter named `value` which type is the type of the property on the type `T` , methods that returns an object of type `BuilderWithTypeMethods<T>`. The definition of this method is done with `(value: T[K]) => BuilderWithTypeMethods<T>` .

We can also make use of the standard typescript type  `Partial<T>` , that from an object type builds another one with all of its properties optional, to enforce the fact that the resulting object of the builder might not have all its properties set.
```typescript
type Partial<T> = {
    [P in keyof T]?: T[P]
}
```
# Using our newly defined types
We can then use this `BuilderWithTypeMethods<T>`  and the `Partial<T>` to enhance our builder class so that the builder class exposes methods that match the properties of the  type of the object building built & enforcing the fact that the built object might not be complete.

```typescript
type BuilderWithTypeMethods<T> = EntityBuilder<T> & {
  [K in keyof T]:
  (value: T[K]) => BuilderWithTypeMethods<T>
}
export default class EntityBuilder<BuiltEntityType> {

  public static getA<StaticBuiltEntityType>(TCreator: new () => StaticBuiltEntityType) {

    return new EntityBuilder(TCreator) as unknown as BuilderWithTypeMethods<StaticBuiltEntityType>
  }

  public static getAn<StaticBuiltEntityType>(TCreator: new () => StaticBuiltEntityType) {
    return EntityBuilder.getA(TCreator)
  }

  protected builtEntity: Partial<BuiltEntityType>
  private creator: new () => BuiltEntityType

  constructor(TCreator: new () => BuiltEntityType) {
    this.creator = TCreator
    this.builtEntity = new this.creator()
  }

  public build() {
    const returnedObj = this.builtEntity
    this.builtEntity = new this.creator()
    return returnedObj
  }

}
```
# Conclusion
With this updated code our sample code show that it is more usable

![Step 3 - Errors on valuated properties.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1648762601718/H5ThV378X.png)

It is better, but there is still ways for improvements, first one would to have better method name (`withKind` instead of `kind`) and second one would be to have the correct `undefined`  status on fields.

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](https://gitlab.com/ArthurCrl/berlingo-ts)
