diff --git a/docs/typed/isResult.mdx b/docs/typed/isResult.mdx index f874ba2a..8c5ce5c9 100644 --- a/docs/typed/isResult.mdx +++ b/docs/typed/isResult.mdx @@ -15,10 +15,6 @@ import * as _ from 'radashi' _.isResult([undefined, 42]) // => true _.isResult([new Error(), undefined]) // => true -// Result tuples cannot have both a value and an error, or neither. -_.isResult([undefined, undefined]) // => false -_.isResult([new Error(), true]) // => false - // Tuple must be of length 2. _.isResult([new Error()]) // => false _.isResult([undefined, true, undefined]) // => false @@ -27,6 +23,9 @@ _.isResult([undefined, true, undefined]) // => false _.isResult([]) // => false _.isResult({}) // => false _.isResult(null) // => false + +// Result tuples cannot have both a value and an error. +_.isResult([new Error(), true]) // => false ``` Also see the related [isResultOk](/typed/isResultOk) and [isResultErr](/typed/isResultErr) functions. @@ -38,11 +37,9 @@ Also see the related [isResultOk](/typed/isResultOk) and [isResultErr](/typed/is “Results” are tuples of 2 elements (an **error** and a **result value**). - The first element is always the **error**, or `undefined` if the operation was successful. -- The second element is always the **result value**, or `undefined` if the operation failed. +- The second element is always the **result value**, unless an error occurred. - These tuples are represented by the `Result` type. - A default error type of `Error` is used when no error type is explicitly defined (e.g. `Result`). -- The default error type is _not_ `unknown` because we assume you're following best practices and so you avoid throwing anything but `Error` objects. -- You're free to define the error type to be anything (like `Result`), not just `Error` types. ### Ok and Err @@ -56,6 +53,8 @@ The names "Ok" and "Err" are inspired by Rust's `std::result` module. To check for an `Ok` result, do this: ```ts +declare const value: unknown + if (isResult(value) && value[0] == null) { value // <-- now an Ok type value[1] // <-- This is the resulting value! @@ -65,8 +64,12 @@ if (isResult(value) && value[0] == null) { To check for an `Err` result, do this: ```ts +declare const value: unknown + if (isResult(value) && value[0] != null) { value // <-- now an Err type value[0] // <-- This is the error! } ``` + +You can also use the `isResultOk` and `isResultErr` functions to check for `Ok` and `Err` results respectively. diff --git a/src/typed/isResult.ts b/src/typed/isResult.ts index de8b2ab8..6110b475 100644 --- a/src/typed/isResult.ts +++ b/src/typed/isResult.ts @@ -1,4 +1,4 @@ -import { isArray, type Result } from 'radashi' +import { isArray, isError, type Result } from 'radashi' /** * Returns true if the value is a `Result` tuple. @@ -9,10 +9,6 @@ import { isArray, type Result } from 'radashi' * isResult([undefined, 42]) => true * isResult([new Error(), undefined]) => true * - * // Result tuples cannot have both a value and an error, or neither. - * isResult([undefined, undefined]) => false - * isResult([new Error(), true]) => false - * * // Tuple must be of length 2. * isResult([new Error()]) => false * isResult([undefined, true, undefined]) => false @@ -21,12 +17,15 @@ import { isArray, type Result } from 'radashi' * isResult([]) => false * isResult({}) => false * isResult(null) => false + * + * // Result tuples cannot have both a value and an error. + * isResult([new Error(), true]) => false * ``` */ -export function isResult(value: unknown): value is Result { +export function isResult(value: unknown): value is Result { return ( isArray(value) && value.length === 2 && - (value[0] === undefined) !== (value[1] === undefined) + (isError(value[0]) ? value[1] : value[0]) === undefined ) } diff --git a/src/typed/isResultErr.ts b/src/typed/isResultErr.ts index 6f526bb1..56aeda3f 100644 --- a/src/typed/isResultErr.ts +++ b/src/typed/isResultErr.ts @@ -10,7 +10,7 @@ import { type Err, isResult } from 'radashi' * isResultErr([undefined, "hello"]) // false * ``` */ -export function isResultErr( +export function isResultErr( value: unknown, ): value is Err { return isResult(value) && value[0] !== undefined diff --git a/src/types.ts b/src/types.ts index fc2edd84..f8872113 100644 --- a/src/types.ts +++ b/src/types.ts @@ -123,7 +123,7 @@ export type Ok = [err: undefined, result: TResult] * // ^? [TypeError | MyCoolCustomError, undefined] * ``` */ -export type Err = [err: NonNullable, result: undefined] +export type Err = [err: TError, result: undefined] /** * A result tuple. @@ -139,9 +139,9 @@ export type Err = [err: NonNullable, result: undefined] * // ^? Ok | Err * ``` */ -export type Result = +export type Result = | Ok - | Err> + | Err /** * A promise that resolves to a result tuple. @@ -155,12 +155,12 @@ export type Result = * // ^? Promise | Err> * ``` */ -export type ResultPromise = Promise< - [NonNullable] extends [never] +export type ResultPromise = Promise< + [TError] extends [never] ? Ok : [TResult] extends [never] - ? Err> - : Result> + ? Err + : Result > /** diff --git a/tests/typed/isResult.test.ts b/tests/typed/isResult.test.ts index 4f5b87ce..028f0ba3 100644 --- a/tests/typed/isResult.test.ts +++ b/tests/typed/isResult.test.ts @@ -4,10 +4,11 @@ describe('isResult', () => { test('should return true for valid Result tuples', () => { expect(_.isResult([undefined, 42])).toBe(true) expect(_.isResult([new Error(), undefined])).toBe(true) + expect(_.isResult([new TypeError(), undefined])).toBe(true) + expect(_.isResult([undefined, undefined])).toBe(true) }) test('should return false for invalid Result tuples', () => { - expect(_.isResult([undefined, undefined])).toBe(false) expect(_.isResult([new Error(), true])).toBe(false) expect(_.isResult([new Error()])).toBe(false) expect(_.isResult([undefined, true, undefined])).toBe(false)