import { Effect, Match, pipe} from 'effect';
// Base class
abstract class FooError {
// As we are using 'string' type we will not
// have type information when catching errors
// later!
constructor(readonly _tag: string){}
}
interface Foo {
bar: (value: string) => Effect.Effect<string, FooError>
}
// First implementation
class SomeError extends FooError {
constructor(readonly message: string) {
super("SomeError")
}
}
class SomeImplementation implements Foo {
bar = (v: string) => Effect.if( !!Math.round(Math.random()), {
onTrue: () => Effect.succeed(v),
onFalse: () => Effect.fail(new SomeError("SomeImplementation"))
})
}
// Second implementation
class AnotherError extends FooError {
constructor(readonly message: string) {
super("AnotherError")
}
}
class AnotherImplementation implements Foo {
bar = (v: string) => Effect.if( !!Math.round(Math.random()), {
onTrue: () => Effect.succeed(v),
onFalse: () => Effect.fail(new AnotherError("AnotherImplementation"))
})
}
// What would be best practices for a common interface but different errors?
function Question(foo: Foo) {
return pipe(
foo.bar("baz"),
Effect.catchAll(e => pipe(
Match.value(e),
// How to have the type system guide in handling all possible errors here?
Match.orElse(() => Effect.die("unhandled error"))
))
)
}
import { Effect, Match, pipe} from 'effect';
// Base class
abstract class FooError {
// As we are using 'string' type we will not
// have type information when catching errors
// later!
constructor(readonly _tag: string){}
}
interface Foo {
bar: (value: string) => Effect.Effect<string, FooError>
}
// First implementation
class SomeError extends FooError {
constructor(readonly message: string) {
super("SomeError")
}
}
class SomeImplementation implements Foo {
bar = (v: string) => Effect.if( !!Math.round(Math.random()), {
onTrue: () => Effect.succeed(v),
onFalse: () => Effect.fail(new SomeError("SomeImplementation"))
})
}
// Second implementation
class AnotherError extends FooError {
constructor(readonly message: string) {
super("AnotherError")
}
}
class AnotherImplementation implements Foo {
bar = (v: string) => Effect.if( !!Math.round(Math.random()), {
onTrue: () => Effect.succeed(v),
onFalse: () => Effect.fail(new AnotherError("AnotherImplementation"))
})
}
// What would be best practices for a common interface but different errors?
function Question(foo: Foo) {
return pipe(
foo.bar("baz"),
Effect.catchAll(e => pipe(
Match.value(e),
// How to have the type system guide in handling all possible errors here?
Match.orElse(() => Effect.die("unhandled error"))
))
)
}