Skip to content

Instantly share code, notes, and snippets.

@chriskrycho
Created December 1, 2018 21:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chriskrycho/97a68e6aaec2e6979275bfada7300789 to your computer and use it in GitHub Desktop.
Save chriskrycho/97a68e6aaec2e6979275bfada7300789 to your computer and use it in GitHub Desktop.
Thinking about `Maybe` and TS and structural typing and…
// A spike: `Maybe` for a pure-FP approach, which doesn't require a container
// type, and which could provide helper functions just as True Myth does today.
// Most of the mechanics here are the same, but it drops the container types in
// favor of just using TS's knowledge of `null` and `undefined`.
//
// The big downside is that people *can* still use `!` or explicit casts to get
// out of this; with the container types those kinds of coercions simply aren't
// allowed.
//
// A related question: what would something like `Either` look like in this kind
// of approach? I don't think you even *could* do it, off the top of my head:
// you don't have any way to distinguish between the variants (`null` and
// `undefined` are special cases in TS).
type Maybe<T> = T | null | undefined;
const isSome = <T>(m: Maybe<T>): m is T =>
m !== null && m !== undefined;
function map<T, U>(fn: (t: T) => U, m: Maybe<T>): Maybe<U>;
function map<T, U>(fn: (t: T) => U): (m: Maybe<T>) => Maybe<U>;
function map<T, U>(
fn: (t: T) => U,
m?: Maybe<T>
): Maybe<U> | ((t: Maybe<T>) => Maybe<U>) {
const op = (a: Maybe<T>) => isSome(a) ? fn(a) : null;
return arguments.length === 2 ? op(m) : op;
}
let len = (s: string) => s.length;
let a = map(len)(null);
let b = map(len)('whaaat uuuuup');
// this is a type error because of `strictNullChecks: true`:
let c = b + 2;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment