Skip to content

Instantly share code, notes, and snippets.

@nythrox
Last active May 5, 2022 19:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nythrox/bb369026dcecf710233582e7cbe1955b to your computer and use it in GitHub Desktop.
Save nythrox/bb369026dcecf710233582e7cbe1955b to your computer and use it in GitHub Desktop.
Typescript do notation (using generator functions)
// user: Either<string, { name: string, age: number }>
const user = doEither(function*() {
// name: string
const name = yield* Right("test")
// age: number
const age = Math.random() > 0.5 ? yield* Right(100) : yield* Left("oopsies")
return {
name,
age
}
})
// user: Either<string, { name: string, age: number }>
const user = doEither(function*() {
// name: string
const name = yield* Right("test")
// age: number
const age = Math.random() > 0.5 ? yield* Right(100) : yield* Left("oopsies")
return {
name,
age
}
})
function doEither<
R,
Ftr extends Either<any, any>,
L = Ftr extends Either<infer L, any> ? L : never
>(
fun: () => Generator<Ftr, R, any>
): Either<L, R> {
const iterator = fun()
const state = iterator.next()
function run(state: any): any {
if (state.done) {
return Right(state.value)
}
return state.value.chain((val: any) => {
return run(iterator.next(val))
})
}
return run(state)
}
export interface Either<L,R> {
[Symbol.iterator]: () => Iterator<Either<L, R>, R, any>
}
Either.prototype[Symbol.iterator] = function*() {
return (yield this) as any
}
@louis030195
Copy link

Cool :) somehow reminds me of Rust stuff https://docs.rs/either/1.6.1/either/enum.Either.html

@nythrox
Copy link
Author

nythrox commented Nov 1, 2021

Yep, it's trying to bring the functional "do notation" to Typescript so we can use it in monadic structures like Either, Promise, Array, etc. Rust seems to be able to have do notation with macros

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment