Last active
December 14, 2023 22:55
-
-
Save acidstorm/f201036811255411df8bafb16c99c7c6 to your computer and use it in GitHub Desktop.
Fun with builders in TS
This file contains 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
// Fun with the builder pattern | |
type ObjectBuilder<T> = { | |
[K in keyof T as Setter<K>]: (value: T[K]) => void | |
} & { | |
[K in keyof T as Getter<K>]: () => T[K] | |
} | |
& Builder<T> | |
type Setter<T> = T extends infer U extends string ? `set${Capitalize<U>}` : never | |
type Getter<T> = T extends infer U extends string ? `get${Capitalize<U>}` : never | |
type Builder<T> = { build: () => T } | |
const createBuilder = <T>() => { | |
const builder: ObjectBuilder<T> = {} as ObjectBuilder<T> | |
function getPropertyFromGetterSetter(property: string) { | |
const sliced = property.slice(3); | |
const firstLetter = sliced[0].toLowerCase(); | |
const rest = sliced.slice(1); | |
return firstLetter + rest; | |
} | |
const proxyHandler = { | |
get(target, prop) { | |
if (prop === 'build') { | |
return () => structuredClone(builder) | |
} | |
if (prop.startsWith("set")) { | |
return (newValue) => { | |
target[getPropertyFromGetterSetter(prop)] = newValue; | |
}; | |
} | |
if (prop.startsWith("get")) { | |
return () => target[getPropertyFromGetterSetter(prop)]; | |
} | |
}, | |
}; | |
return new Proxy(builder, proxyHandler) as typeof builder | |
} | |
type K = { item: string, classic: boolean } | |
class L { | |
items: string | |
classics: boolean | |
} | |
const f = createBuilder<K>() | |
f.setClassic(false) | |
const initialF = f.build() | |
f.setClassic(true) | |
const postUpdateF = f.build() | |
const g = createBuilder<L>() | |
const initialG = g.build() | |
console.log({ initialF, postUpdateF, initialG }) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment