Closed TheWix closed 1 year ago
There is no Either
class in purify, if you look at the source you will see Either
is just a plain object with functions which return instances of the Left
and Right
classes. This is for performance reasons.
Let me know if this works for you: https://github.com/gigobyte/purify/issues/242#issuecomment-691527110
So, this got me close, but I could only get it to work with an instance like Right("")
. I think it is because EitherTypeRef
isn't exported.
Oh, if you want to extend Either
as in Either
the purify-ts export, it's just an object, so there's not much benefit in doing so. One option is to do this:
import { Either as PurifyEither } from 'purify-ts/es/Either'
type EitherTypeRef = typeof Either
interface MyEitherTypeRef extends EitherTypeRef {
fromPredicate: any
}
const Either: MyEitherTypeRef = {
...PurifyEither ,
fromPredicate: () => {}
}
export { Either }
and then
import { Either } from 'your-library'
OR (my recommendation) just export fromPredicate
as a helper function, there's no need for it to be inside the Either
object.
Yea, I have it as a helper function now. I just wanted to see if I could hang it off Either
like the other constructor functions so they were all in one place instead of people having to remember whether it is an extension vs the original. C# has the concept of Extension Methods so that is what I was going for.
I also had the need to extend Either / EitherAsync but mostly "instance" methods. I resorted to using a pattern similar to what purifree did (see here). My additions?
interface Either<L, R> {
// convert an Either into an EitherAsync in a chain
toAsync(): EitherAsync<L, R>;
// execute effect regardless of whether "this" is Left or Right (EitherAsync already has that)
finally(effect: () => any): this;
// assert some condition, return Left result if the predicate returns false (super handy for validation)
assert(predicate: (value: R) => boolean, left: L | ((value: R) => L)): this;
// minor helper to return Either<L, void> from a chain
void(): Either<L, void>;
}
interface EitherAsync<L, R> {
// as above, just async variant (the predicate is sync, tho)
assert(predicate: (value: R) => boolean, left: L | ((value: R) => L)): this;
// return a Left if a chain does not return within an allotted time
timeout(ms: number, left: L | (() => L)): this;
// execute async effect (Promise or EitherAsync) regardless of whether "this" is Left or Right
finallyAsync(cb: EitherAsync<unknown, unknown> | (() => PromiseLike<unknown>)): this;
}
Thank you for this awesome library - it's a real pleasure to use (and I've grown to love how cool EitherAsync
is!)
@atomictag Ooh, didn't know about this library either! Yea, the issue is that EitherTypeRef
isn't exported. I actually got it working by doing this:
import { Either as OrginalEither } from "../../node_modules/purify-ts/es/Either.js";
module "purify-ts" {
export * from "purify-ts";
export interface EitherTypeRef2 extends (typeof OrginalEither) {
fromPredicate: <L, R>(predicate: (v: unknown) => v is R, onLeft: (v: unknown) => L) => (v: unknown) => OrginalEither<L, R>
}
export const Either: EitherTypeRef2;
export type Either<L,R> = OrginalEither<L, R>;
}
At this point, I'll probably just create my own extension, though. I'll hav a look at purifree
to see if it has some helpers I have been writing.
Hello,
I am attempting to write a library to extend some of the classes with useful methods without resorting to inheritance, for example:
What I am running into:![image](https://user-images.githubusercontent.com/362449/222218096-39cf8c33-df75-4ff5-b4b6-f65b426306d6.png)
I haven't tried extending classes like this before using declaration merging. I dunno if Typescript is getting confused because
Either
is both an interface representing an instance of anEither<L, R>
as well as adeclared
object of typeEitherTypeRef
representing the static functions ofEIther
.Any advice on this would be helpful, thank you!