Skip to content

Instantly share code, notes, and snippets.

@tail-call
Last active July 16, 2023 13:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tail-call/2523904210e1d4866914f4d9e762e5f7 to your computer and use it in GitHub Desktop.
Save tail-call/2523904210e1d4866914f4d9e762e5f7 to your computer and use it in GitHub Desktop.

Either for TypeScript

Is this working? I don't know.

type Result<T> = {
value: T, error: undefined
} | {
value: undefined, error: Error
};
function makeResult<T>(value: T): Result<T> {
return { value, error: undefined };
}
function makeError<T>(error: Error): Result<T> {
return { value: undefined, error };
}
function mapResult<T, V>(result: Result<T>, transform: (value: T) => V): Result<V> {
if (result.value) {
return { value: transform(result.value), error: undefined };
} else if (result.error) {
return { value: undefined, error: result.error };
} else {
return { value: undefined, error: new Error("malformed Result object") };
}
}
function checkValidIndex<T>(array: T[], index: number): Result<true> {
if (Number.isInteger(index) && index >= 0 && index < array.length) {
return makeResult(true);
} else {
return makeError(new Error("invalid index: " + index));
}
}
function getIndex<T>(array: T[], index: number): Result<T> {
return mapResult(checkValidIndex(array, index), () => {
return array[index];
});
}
class Either<Left, Right> {
left?: Left
right?: Right
private constructor(left: Left | undefined, right: Right | undefined) {
this.left = left;
this.right = right;
}
static left<Left, Right>(left: Left): Either<Left, Right> {
return new Either(left, undefined as unknown as Right);
}
static right<Left, Right>(right: Right): Either<Left, Right> {
return new Either(undefined as unknown as Left, right);
}
flatMap<NewLeft, NewRight>(
leftMap: (left: Left) => NewLeft, rightMap: (right: Right) => NewRight
): Either<NewLeft, NewRight> {
if (this.left) {
return Either.left(leftMap(this.left));
} else if (this.right) {
return Either.right(rightMap(this.right));
} else {
throw new Error("Major type fuckup happened");
}
}
}
type Either3<T, U, V> = Either<T, Either<U, V>>;
//type Either4<T, U, V, W> = Either<Either<T, U>, Either<V, W>>;
type Either4<T, U, V, W> = Either<T, Either3<U, V, W>>;
function arrayOrString<T>(kind: "array" | "string"): Either<Array<T>, string> {
if (kind === "array") {
return Either.left([]);
} else {
return Either.right("");
}
}
const x = arrayOrString("array");
const y = x.flatMap((array) => array.concat(array), (string) => string + "wow");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment