Skip to content

Instantly share code, notes, and snippets.

@zetavg
Last active March 15, 2019 01:29
Show Gist options
  • Save zetavg/e9a188ff839892ac6131d0899ebeef51 to your computer and use it in GitHub Desktop.
Save zetavg/e9a188ff839892ac6131d0899ebeef51 to your computer and use it in GitHub Desktop.
Nix Override Design Pattern (https://nixos.org/nixos/nix-pills/override-design-pattern.html) in JavaScript.
const makeOverridable = obj => ({
...obj,
override: overrides => makeOverridable({
...obj,
...overrides,
}),
})
@zetavg
Copy link
Author

zetavg commented Mar 15, 2019

Example usage:

const obj = makeOverridable({ foo: 1, bar: 2 }) // => { foo: 1, bar: 2, override: ƒ }
const obj2 = obj.override({ baz: 3 }) // => { foo: 1, bar: 2, baz: 3, override: ƒ }
const obj3 = obj2.override({ bar: 42 }) // => { foo: 1, bar: 42, baz: 3, override: ƒ }

@zetavg
Copy link
Author

zetavg commented Mar 15, 2019

makeOverridable for functions that have type ({ ...args }) => ({ ...obj }) should actually be:

const makeOverridableMaker = f => args => ({
  ...f(args),
  override: argOverrides => makeOverridableMaker(f)({
    ...args,
    ...argOverrides,
  }),
})

Example usage:

const makeDouble = obj => Object.entries(obj).map(([k, v]) => [k, v * 2]).reduce((obj, entry) => (obj[entry[0]] = entry[1], obj), {})
const makeDoubleAndOverridable = makeOverridableMaker(makeDouble)
const obj = makeDoubleAndOverridable({ a: 1, b: 2 }) // => { a: 2, b: 4, override: ƒ }
const obj2 = obj.override({ c: 3 }) // => { a: 2, b: 4, c: 6, override: ƒ }
const obj3 = obj2.override({ b: 21 }) // => { a: 2, b: 42, c: 6, override: ƒ }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment