Skip to content

Commit

Permalink
[dsch] implementation of Result::asTuple
Browse files Browse the repository at this point in the history
  • Loading branch information
DScheglov committed Sep 28, 2024
1 parent 6b7382d commit c3deea3
Show file tree
Hide file tree
Showing 5 changed files with 270 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/Err.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ export class ErrImpl<E> implements Err<E> {
apply() {
return this;
}
asTuple(): readonly [ok: false, value: undefined, error: E] {
return [false, undefined, this.error] as const;
}
}

Object.defineProperty(ErrImpl, 'name', { enumerable: false, value: 'Err' });
Expand Down
3 changes: 3 additions & 0 deletions src/Ok.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ export class OkImpl<T> implements Ok<T> {

return Array.isArray(argValues) ? ok(this.value(...argValues)) : argValues;
}
asTuple(): readonly [ok: true, value: T, error: undefined] {
return [true, this.value, undefined] as const;
}
}

Object.defineProperty(OkImpl, 'name', { enumerable: false, value: 'Ok' });
Expand Down
254 changes: 254 additions & 0 deletions src/result.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1243,4 +1243,258 @@ describe('Result', () => {
).toEqual(ok([1, 'foo']));
});
});

describe('asTuple', () => {
it('returns a tuple for an Ok result', () => {
expect.assertions(2);
const [isOk, value, error] = ok('foo').asTuple();

if (isOk) {
expect(value).toBe('foo');
expect(error).toBeUndefined();
}
});

it('returns a tuple for an Ok result - pipe', () => {
expect.assertions(2);
const [isOk, value, error] = pipe(ok('foo'), R.asTuple);

if (isOk) {
expect(value).toBe('foo');
expect(error).toBeUndefined();
}
});

it('returns a correctly typed tuple for an Ok result', () => {
const result = ok('foo');
const [isOk, value, error] = result.asTuple();

const checkStatus: Expect<Equal<typeof isOk, true>> = true;
expect(checkStatus).toBe(true);

const checkValue: Expect<Equal<typeof value, string>> = true;
expect(checkValue).toBe(true);

const checkError: Expect<Equal<typeof error, undefined>> = true;
expect(checkError).toBe(true);
});

it('returns a correctly typed tuple for an Ok result - pipe', () => {
const result = ok('foo');
const [isOk, value, error] = pipe(result, R.asTuple);

const checkStatus: Expect<Equal<typeof isOk, boolean>> = true;
expect(checkStatus).toBe(true);

const checkValue: Expect<Equal<typeof value, string | undefined>> = true;
expect(checkValue).toBe(true);

const checkError: Expect<Equal<typeof error, undefined>> = true;
expect(checkError).toBe(true);
});

it('returns a tuple for an Ok result typed as Result', () => {
expect.assertions(2);
const result = ok('foo') as Result<string, 'ERR'>;
const [isOk, value, error] = result.asTuple();

if (isOk) {
expect(value).toBe('foo');
expect(error).toBeUndefined();
}
});

it('returns a tuple for an Ok result typed as Result - pipe', () => {
expect.assertions(2);
const result = ok('foo') as Result<string, 'ERR'>;
const [isOk, value, error] = pipe(result, R.asTuple);

if (isOk) {
expect(value).toBe('foo');
expect(error).toBeUndefined();
}
});

it('returns a correctly typed tuple for an Ok result typed as Result', () => {
const result = ok('foo') as Result<string, 'ERR'>;
const [isOk, value, error] = result.asTuple();

const checkStatus: Expect<Equal<typeof isOk, boolean>> = true;
expect(checkStatus).toBe(true);

const checkValue: Expect<Equal<typeof value, string | undefined>> = true;
expect(checkValue).toBe(true);

const checkError: Expect<Equal<typeof error, 'ERR' | undefined>> = true;
expect(checkError).toBe(true);
});

it('returns a correctly typed tuple for an Ok result typed as Result - pipe', () => {
const result = ok('foo') as Result<string, 'ERR'>;
const [isOk, value, error] = pipe(result, R.asTuple);

const checkStatus: Expect<Equal<typeof isOk, boolean>> = true;
expect(checkStatus).toBe(true);

const checkValue: Expect<Equal<typeof value, string | undefined>> = true;
expect(checkValue).toBe(true);

const checkError: Expect<Equal<typeof error, 'ERR' | undefined>> = true;
expect(checkError).toBe(true);
});

it('returns a tuple that could correctly discriminated for an Ok result typed as Result', () => {
expect.assertions(2);
const result = ok('foo') as Result<string, 'ERR'>;
const [isOk, value, error] = result.asTuple();

if (isOk) {
const checkValue: Expect<Equal<typeof value, string>> = true;
expect(checkValue).toBe(true);

const checkError: Expect<Equal<typeof error, undefined>> = true;
expect(checkError).toBe(true);
}
});

it('returns a tuple that could correctly discriminated for an Ok result typed as Result - pipe', () => {
expect.assertions(2);
const result = ok('foo') as Result<string, 'ERR'>;
const [isOk, value, error] = pipe(result, R.asTuple);

if (isOk) {
const checkValue: Expect<Equal<typeof value, string>> = true;
expect(checkValue).toBe(true);

const checkError: Expect<Equal<typeof error, undefined>> = true;
expect(checkError).toBe(true);
}
});

it('returns a tuple for an Err result', () => {
expect.assertions(2);
const [isOk, value, error] = err('foo').asTuple();

if (!isOk) {
expect(value).toBeUndefined();
expect(error).toBe('foo');
}
});

it('returns a tuple for an Err result - pipe', () => {
expect.assertions(2);
const [isOk, value, error] = pipe(err('foo'), R.asTuple);

if (!isOk) {
expect(value).toBeUndefined();
expect(error).toBe('foo');
}
});

it('returns a correctly typed tuple for an Err result', () => {
const result = err('foo');
const [isOk, value, error] = result.asTuple();

const checkStatus: Expect<Equal<typeof isOk, false>> = true;
expect(checkStatus).toBe(true);

const checkValue: Expect<Equal<typeof value, undefined>> = true;
expect(checkValue).toBe(true);

const checkError: Expect<Equal<typeof error, string>> = true;
expect(checkError).toBe(true);
});

it('returns a correctly typed tuple for an Err result - pipe', () => {
const result = err('foo');
const [isOk, value, error] = pipe(result, R.asTuple);

const checkStatus: Expect<Equal<typeof isOk, boolean>> = true;
expect(checkStatus).toBe(true);

const checkValue: Expect<Equal<typeof value, unknown>> = true;
expect(checkValue).toBe(true);

const checkError: Expect<Equal<typeof error, string | undefined>> = true;
expect(checkError).toBe(true);
});

it('returns a tuple for an Err result typed as Result', () => {
expect.assertions(2);
const result = err('ERR') as Result<string, 'ERR'>;
const [isOk, value, error] = result.asTuple();

if (!isOk) {
expect(value).toBeUndefined();
expect(error).toBe('ERR');
}
});

it('returns a tuple for an Err result typed as Result - pipe', () => {
expect.assertions(2);
const result = err('ERR') as Result<string, 'ERR'>;
const [isOk, value, error] = pipe(result, R.asTuple);

if (!isOk) {
expect(value).toBeUndefined();
expect(error).toBe('ERR');
}
});

it('returns a correctly typed tuple for an Err result typed as Result', () => {
const result = err('ERR') as Result<string, 'ERR'>;
const [isOk, value, error] = result.asTuple();

const checkStatus: Expect<Equal<typeof isOk, boolean>> = true;
expect(checkStatus).toBe(true);

const checkValue: Expect<Equal<typeof value, string | undefined>> = true;
expect(checkValue).toBe(true);

const checkError: Expect<Equal<typeof error, 'ERR' | undefined>> = true;
expect(checkError).toBe(true);
});

it('returns a correctly typed tuple for an Err result typed as Result - pipe', () => {
const result = err('ERR') as Result<string, 'ERR'>;
const [isOk, value, error] = pipe(result, R.asTuple);

const checkStatus: Expect<Equal<typeof isOk, boolean>> = true;
expect(checkStatus).toBe(true);

const checkValue: Expect<Equal<typeof value, string | undefined>> = true;
expect(checkValue).toBe(true);

const checkError: Expect<Equal<typeof error, 'ERR' | undefined>> = true;
expect(checkError).toBe(true);
});

it('returns a tuple that could correctly discriminated for an Err result typed as Result', () => {
expect.assertions(2);
const result = err('ERR') as Result<string, 'ERR'>;
const [isOk, value, error] = result.asTuple();

if (!isOk) {
const checkValue: Expect<Equal<typeof value, undefined>> = true;
expect(checkValue).toBe(true);

const checkError: Expect<Equal<typeof error, 'ERR'>> = true;
expect(checkError).toBe(true);
}
});

it('returns a tuple that could correctly discriminated for an Err result typed as Result - pipe', () => {
expect.assertions(2);
const result = err('ERR') as Result<string, 'ERR'>;
const [isOk, value, error] = pipe(result, R.asTuple);

if (!isOk) {
const checkValue: Expect<Equal<typeof value, undefined>> = true;
expect(checkValue).toBe(true);

const checkError: Expect<Equal<typeof error, 'ERR'>> = true;
expect(checkError).toBe(true);
}
});
});
});
8 changes: 8 additions & 0 deletions src/sync-methods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,11 @@ export const biChain =
) =>
(result: Result<T, E>): Result<TS | ES, TF | EF> =>
result.biChain(okFn, errFn);

export const asTuple: {
<T, E>(
result: Result<T, E>,
):
| readonly [ok: true, value: T, error: undefined]
| readonly [ok: false, value: undefined, error: E];
} = (result: Result<unknown, unknown>): any => result.asTuple();
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ export interface Ok<T> extends ResultInterface<T, never> {
readonly value: T;
readonly isOk: true;
readonly isErr: false;
asTuple(): readonly [ok: true, value: T, error: undefined];
}

export interface Err<E> extends ResultInterface<never, E> {
readonly error: E;
readonly isOk: false;
readonly isErr: true;
asTuple(): readonly [ok: false, value: undefined, error: E];
}

export interface ResultInterface<T, E> {
Expand Down

0 comments on commit c3deea3

Please sign in to comment.