Skip to content

Instantly share code, notes, and snippets.

@mikehadlow
Last active May 1, 2023 22:52
Show Gist options
  • Save mikehadlow/65347bade6210c73e216c58e183d7c60 to your computer and use it in GitHub Desktop.
Save mikehadlow/65347bade6210c73e216c58e183d7c60 to your computer and use it in GitHub Desktop.
Simple monadic result type in Typescript
// Result
type Success<S> = { success: true, value: S }
type Failure<F> = { success: false, message: F }
type Bindable<S, F> = {
bind: <B,>(func: (input: S) => Result<B, F>) => Result<B, F>
}
type Result<S, F> = (Success<S> | Failure<F>) & Bindable<S, F>
const toResult = <S, F>(input: S): Result<S, F> => ({
success: true,
value: input,
bind: func => func(input)
})
const toFailure = <S, F>(message: F): Result<S, F> => ({
success: false,
message: message,
bind: _ => toFailure(message)
})
// Let's try it out...
const isEven = (input: number): Result<number, string> => {
if(input % 2 === 0) {
return toResult(input)
}
return toFailure("Not even!")
}
const divisibleBy3 = (input: number): Result<number, string> => {
if(input % 3 === 0) {
return toResult(input)
}
return toFailure("Not divisible by 3!")
}
const testWith = (input: number): void => {
const inputResult = toResult<number, string>(input)
const result = inputResult.bind(isEven).bind(divisibleBy3)
if(result.success) {
console.log(`${input} Success: ${result.value}`)
} else {
console.log(`${input} Failure: ${result.message}`)
}
}
const main = () => {
testWith(6)
testWith(8)
testWith(9)
}
main()