Type-safe object builder in TS
Matthias Hryniszak

Matthias Hryniszak @padcom

About: I'm a passionate software developer. I like coding :) It's fun!!!

Location:
Gliwice
Joined:
Mar 23, 2020

Type-safe object builder in TS

Publish Date: Oct 24 '22
5 0

Long story short - object builder pattern in TypeScript :)

type Builder<Source extends object, Target> = {
  [Prop in keyof Required<Source>]: (value: Source[Prop]) => Builder<Source, Target>
} & {
  build(): Target
}
Enter fullscreen mode Exit fullscreen mode

This type defines an object that will have methods of the same name as the Source object plus the build() method.

Here's an implementation thereof using Proxy:

function clone<S, T>(source: S): T {
  return JSON.parse(JSON.stringify(source))
}

function builder<
  Source extends object,
  Target
>(
  source: Source,
  convert: (source: Source) => Target = clone
): Builder<Source, Target> {

  const proxy = new Proxy<Builder<Source, Target>>(
    source as any, {
    get(target, prop: string, receiver) {
      if (prop === 'build') return build
      else return (value: any) => setter(
        prop as keyof Source, value
      )
    }
  });

  function build(): Target {
    return convert(source)
  }

  function setter(
    prop: keyof Source,
    value: any
  ): Builder<Source, Target> {
    source[prop] = value
    return proxy
  }

  return proxy
}
Enter fullscreen mode Exit fullscreen mode

And here's how you could use it:

const b = builder(
  {
    x: 1,
    y: 'Hello'
  },
  source => ({
    o1: { a: source.y, b: source.x },
    o2: { p1: source.x, p2: source.y },
  })
)

console.log(b.x(3).y('2').build())
Enter fullscreen mode Exit fullscreen mode

Each call to the builder methods is type-safe so it should be easy to work with it :)

Happy coding!

Comments 0 total

    Add comment