Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save michael-wolfenden/729dd91632334039c4a9c0aeaad29cfd to your computer and use it in GitHub Desktop.
Save michael-wolfenden/729dd91632334039c4a9c0aeaad29cfd to your computer and use it in GitHub Desktop.
// Builders
class SimpleBuilder {
constructor(private current = {}) {
}
prop(key: string, value: any) {
return new SimpleBuilder({ ...this.current, ...{ [key]: value } });
}
build<R>() {
return <R>this.current;
}
}
class TypedBuilder<T> {
constructor(private current = {}) {
}
prop<P extends keyof T, V extends T[P]>(key: P, value: V) {
return new TypedBuilder<T>({ ...this.current, ...{ [key]: value } });
}
build() {
return <T>this.current;
}
}
class AdvanceBuilder<T, R extends {} = {}> {
constructor(private current: R = null) {
}
// P: Only those properties from T that do not exist in R
prop<P extends Exclude<keyof T, keyof R>, V extends T[P]>(key: P, value: V) {
let extra: Pick<T, P> = { [key]: value };
// `instance` is an intersection between our accumulator type (R) and
// the `extra` object created above
let instance = {
...(this.current as object),
...extra
} as R & Pick<T, P>;
return new AdvanceBuilder<T, R & Pick<T, P>>(instance);
}
build(): R {
return this.current;
}
}
// Domain
interface RequestSettings {
protocol: 'http' | 'https';
host: string;
path: string;
query?: string;
headers: { key: string, value: string }[]
}
// Usage
const settings1 = new SimpleBuilder()
.prop('protocol', 'http')
.prop('host', 'test.com')
.prop('path', '/foo/bar')
.prop('headers', [])
.build<RequestSettings>();
const settings2 = new TypedBuilder<RequestSettings>()
.prop('protocol', 'http')
.prop('host', 'test.com')
.prop('path', '/foo/bar')
.prop('headers', [])
.build();
const settings3: RequestSettings = new AdvanceBuilder<RequestSettings>()
.prop('protocol', 'http')
.prop('host', 'test.com')
.prop('path', '/foo/bar')
.prop('headers', [])
.build();
// Logging
alert(JSON.stringify(settings1));
alert(JSON.stringify(settings2));
alert(JSON.stringify(settings3));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment