0
\$\begingroup\$

I have been trying to implement a version of the Maybe functor in Typescript. I'm looking for feedback on whether I can improve the type safety of my implementation. I'm not particularly happy that types like Just<void> or Nothing<number> are not ruled out by the type-system, but I can't see any way to tighten this up.

class Nothing<T> {
  
  fmap<P>(fn: (arg: T) => P): Nothing<P> {
    return new Nothing();
  }

  isJust(): this is Just<T> {
    return false;
  }

  isNothing(): this is Nothing<T> {
    return true;
  }
}

class Just<T> {
  
  constructor(private readonly value: T) {}

  fmap<P>(fn: (arg: T) => P): Maybe<P> {
    const nextVal = fn(this.value);
    if (nextVal === null || nextVal === undefined) {
      return new Nothing();
    }
    return new Just(nextVal);
  }

  isJust(): this is Just<T> {
    return true;
  }

  isNothing(): this is Nothing<T> {
    return false;
  }
}

const Maybe = {
  of<T>(val: T): Maybe<T> {
    if (val === null || val === undefined) {
      return new Nothing();
    }
    return new Just(val);
  }
}

type Maybe<T> = Just<T>|Nothing<T>

Maybe.of(undefined).fmap(x => "foo").fmap(x => console.log(x))
Maybe.of("bar").fmap(x => x + x).fmap(x => console.log(x));
\$\endgroup\$
1
  • \$\begingroup\$ Ruling out Nothing<number> is quite simple: Make Nothing a non-generic object instead of a generic class. Then there can only ever be one Nothing. \$\endgroup\$ Sep 13 at 20:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.