Skip to content

Instantly share code, notes, and snippets.

@luoling8192
Created May 8, 2025 10:39
Show Gist options
  • Select an option

  • Save luoling8192/72ac6bb766a539b02bfdab8b04aa2074 to your computer and use it in GitHub Desktop.

Select an option

Save luoling8192/72ac6bb766a539b02bfdab8b04aa2074 to your computer and use it in GitHub Desktop.
Telegram Search Monad
import { describe, expect, it } from 'vitest'
import { Err, Ok } from './monad'
describe('utils/monad', () => {
it('works in sync', () => {
function testOk() {
return Ok(1)
}
function testErr() {
return Err(new Error('test'))
}
let notError = true
try {
testOk()
}
catch {
notError = false
}
expect(notError).toBe(true)
let error = false
try {
testErr().expect('expect error occurred')
}
catch (err) {
console.error(err)
error = true
}
expect(error).toBe(true)
})
it('works in async', async () => {
async function testOk() {
return Ok(1)
}
async function testErr() {
return Err(new Error('async test'))
}
let notError = true
try {
await testOk()
}
catch {
notError = false
}
expect(notError).toBe(true)
let error = false
try {
(await testErr()).expect('expect async error occurred')
}
catch (err) {
console.error(err)
error = true
}
expect(error).toBe(true)
})
})
import { useLogger } from '@tg-search/common'
export interface Result<T> {
orDefault: (defaultValue: T) => T
orUndefined: () => T | undefined
orElse: (fn: () => T) => T
unwrap: () => T
unwrapOver: (fn: (error: unknown) => void) => T
expect: (message?: string) => T
expectOver: (message?: string, fn?: (error: unknown) => void) => T
map: <U>(fn: (value: T) => U) => Result<U>
mapErr: (fn: (error: unknown) => T) => Result<T>
}
export function Ok<T>(value: T): Result<T> {
return {
orDefault: () => value,
orUndefined: () => value,
orElse: fn => fn(),
unwrap: () => value,
unwrapOver: () => value,
expect: () => value,
expectOver: () => value,
map: (fn) => {
try {
return Ok(fn(value))
}
catch (err: unknown) {
return Err(err instanceof Error ? err : new Error(String(err)))
}
},
mapErr: (_fn) => {
return Ok(value)
},
}
}
export function Err<T>(error: unknown): Result<T> {
useLogger('core:monnad').withError(error).warn('An error occurred')
return {
orDefault: (defaultValue: T) => defaultValue,
orUndefined: () => undefined,
orElse: fn => fn(),
unwrap: () => {
throw error
},
unwrapOver: (fn) => {
fn(error)
throw error
},
expect: (message?: string) => {
const newError = new Error(message ?? 'Result is empty')
newError.cause = error
throw newError
},
expectOver: (message, fn) => {
fn?.(error)
const newError = new Error(message ?? 'Result is empty')
newError.cause = error
throw newError
},
map: () => {
return Err(error)
},
mapErr: (fn) => {
return Err(fn(error))
},
}
}
// export interface Future<T> {
// await: () => Result<Awaited<T>>
// }
// export function Async<T>(fn: () => Promise<T>): Future<T> {
// return {
// await: async () => {
// try {
// return Ok(await fn())
// }
// catch (error) {
// return Err<T>(error)
// }
// },
// }
// }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment