Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

optional: prop for partial keys #168

Open
waynevanson opened this issue Aug 22, 2021 · 3 comments
Open

optional: prop for partial keys #168

waynevanson opened this issue Aug 22, 2021 · 3 comments

Comments

@waynevanson
Copy link

🚀 Feature request

An export from the Optional module called partial.

This request is in progress, I will advise when it's ready.

Current Behavior

There is no way to set a value on a deeply partial key.

Desired Behavior

Suggested Solution

const partial =
  <A, P extends keyof A>(prop: P) =>
  <S>(optional: o.Optional<S, A>): o.Optional<S, NonNullable<A[P]>> => ({
    getOption: pipe(optional, o.prop(prop), o.fromNullable).getOption,
    set: (b) => (s) =>
      pipe(
        optional.getOption(s),
        O.fold(
          () => ({} as A),
          (a) => a,
        ),
        (a) => Object.assign({}, a, { [prop]: b }),
        optional.set,
      )(s),
  })

const options = pipe(
  o.id<Config.ProjectConfig>(),
  o.prop("globals"),
  partial("webdriver"),
  partial("options"),
  partial("capabilities"),
)

Who does this impact? Who is this for?

Describe alternatives you've considered

Additional context

@kalda341
Copy link

This is something that would be very useful to me.
Ideally I would avoid this by having a better datastructure, but this isn't always achievable.
I currently get around this limitation using Lens.fromNullable, but that doesn't exist within the new experimental API.

@waynevanson
Copy link
Author

I actually think it needs to be Lens<S, Option<A>>, so then the laws hold up. That way when it's None we can force it to be the value inside of Some<A>.

Optional seems to ignore stuff when it's not there, which has its own use cases, and I don't think that should be messed with.

@volkanunsal
Copy link

volkanunsal commented Aug 3, 2022

I have a different solution for this. It's a bit simpler.

import * as L from 'monocle-ts/Lens';

function defaultValue<S, T>(value: T) {
  return L.compose<S, T>(
    L.lens(
      (s) => (s ? (s as any as T) : value),
      (a) => () => a as any as S
    )
  );
}

function modDeps<T>(deps: string[]) {
  return pipe(
    L.id<T>(),
    L.prop('deps'),
    defaultValue([]),
    L.modify((s) => ...)
  );
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants