Created
December 1, 2018 21:08
-
-
Save chriskrycho/97a68e6aaec2e6979275bfada7300789 to your computer and use it in GitHub Desktop.
Thinking about `Maybe` and TS and structural typing and…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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