mobily/ts-belt

Clarification on how `D.get` works when key exists but value is undefined

Opened this issue · 1 comments

I have some trouble using D.get and I'm unsure if this is a bug or if I'm misunderstanding the documentation.

Here's a minimal example to show the issue I'm having

const foo: {bar: string | undefined} = {bar: undefined};
pipe(
  foo,
  D.get('bar'),
  O.map(value => value.length) // The type of "value" is string, but its actual value is undefined so it throws
)

I can see the documentation says

Returns Some(value) if the given key exists, otherwise returns None.

In the above example the key does exist, and based on the return type of D.get I guess it becomes ExtractValue<string | undefined> which would end up as Exclude<string | undefined, null | undefined | void> resulting in string, which does not correspond to the actual value being passed to O.map

To resolve this I've gone ahead with the following solution.

const foo: {bar: string | undefined} = {bar: undefined};
pipe(
  foo,
  D.get('bar'),
  O.fromNullable, // This seems to properly wrap the undefined value from `foo.bar` in Option
  O.map(value => value.length) // The type of "value" is string, but its actual value is undefined so it throws
)

seems that it's option's problem, related to #97