unwrap-or
Version:
A TypeScript implementation of Rust's Option and Result types.
609 lines (584 loc) • 13.6 kB
TypeScript
/**
* @module Result
*/
/**
* @since 0.4.0-alpha
*
* Type `Result` is a type that represents either success `Ok(T)`
* and containing a value, or `Err(E)`, representing error
* and containing an error value.
*
* @example
*
* let x: Result<number, string>
*
* x = Ok(42)
* assert_eq!(x, Ok(42))
*
* x = Err('empty')
* assert_eq!(x, Err('empty'))
*/
export interface Result<T, E> {
/**
* @since 0.4.0-alpha
*
* Returns `res` if the result is `Ok`, otherwise returns the `Err` value.
*
* Arguments passed to and are eagerly evaluated;
* if you are passing the result of a function call,
* it is recommended to use `and_then`, which is lazily evaluated.
*
* @example
*
* let x: Result<number, string>
* let y: Result<string, string>
*
* x = Ok(2)
* y = Err("late error")
* assert_eq!(x.and(y), Err("late error"))
*
* x = Err("early error")
* y = Ok("foo")
* assert_eq!(x.and(y), Err("early error"))
*
* x = Err("not a 2")
* y = Err("late error")
* assert_eq!(x.and(y), Err("not a 2"))
*
* x = Ok(2)
* y = Ok("different result type")
* assert_eq!(x.and(y), Ok("different result type"))
*/
and<U>(res: Result<U, E>): Result<T | U, E>;
/**
* @since 0.4.0-alpha
*
* Calls `op` if the result is `Ok`, otherwise returns the `Err` value.
*
* This function can be used for control flow based on `Result` values.
*
* Often used to chain fallible operations that may return `Err`.
*
* @example
*
* let x: Result<number, string>;
* let y: Result<string, string>;
*
* x = Ok(2)
* y = Err("late error")
* assert_eq!(
* x.and_then(() => y),
* Err("late error"),
* )
*
* x = Err("early error")
* y = Ok("foo")
* assert_eq!(
* x.and_then(() => y),
* Err("early error"),
* )
*
* x = Err("not a 2")
* y = Err("late error")
* assert_eq!(
* x.and_then(() => y),
* Err("not a 2"),
* )
*
* x = Ok(2)
* y = Ok("different result type")
* assert_eq!(
* x.and_then(() => y),
* Ok("different result type"),
* )
*/
and_then<U>(op: (value: T) => Result<U, E>): Result<T | U, E>;
// TODO: public err() {}
/**
* @since 0.4.0-alpha
*
* Returns the contained `Ok` value.
*
* Because this method may throw, its use is generally discouraged.
* Instead, prefer to use pattern matching and handle the `Err` case explicitly,
* or call `unwrap_or`, `unwrap_or_else`, or `unwrap_or_default`.
*
* Recommend that expect messages are used to describe the reason
* you expect the `Result` should be `Ok`.
*
* @throws Panics if the value is an `Err`,
* with a panic message including the passed message, and the value of the `Err`.
*
* @example
*
* let x: Result<number, string>
*
* x = Ok(42)
* assert_eq!(x.expect("should return 42"), 42)
*
* x = Err("unknown value")
* assert_err!(
* () => x.expect("should return 42"),
* 'should return 42: "unknown value"',
* )
*/
expect(msg: string): T;
/**
* @since 0.4.0-alpha
*
* Returns the contained `Err` value.
*
* @throws Panics if the value is an `Ok`, with a panic message
* including the passed message, and the content of the Ok.
*
* @example
*
* let x: Result<number, string>
*
* x = Ok(42)
* assert_err!(
* () => x.expect_err("should return unknown error value"),
* "should return unknown error value: 42",
* )
*
* x = Err("unknown error value")
* assert_eq!(
* x.expect_err("should return unknown error value"),
* "unknown error value",
* )
*/
expect_err(msg: string): E;
// TODO: public flatten() {}
/**
* @since 0.4.0-alpha
*
* Calls a function with a reference to the contained value if `Ok`.
*
* Returns the original result.
*
* @example
*
* function get<T>(arr: T[], idx: number): Result<T, string> {
* const item = arr.at(idx)
* return item !== undefined ? Ok(item) : Err("Not found")
* }
*
* const list = [1, 2, 3, 4, 5]
*
* let has_inspected = false
*
* let x = get(list, 2).inspect((_v) => {
* has_inspected = true
* })
*
* assert_eq!(x, Ok(3))
* assert_eq!(has_inspected, true)
*/
inspect(f: (value: T) => void): Result<T, E>;
/**
* @since 0.4.0-alpha
*
* Calls a function with a reference to the contained value if `Err`.
*
* Returns the original result.
*
* @example
*
* function get<T>(arr: T[], idx: number): Result<T, string> {
* const item = arr.at(idx)
*
* return item !== undefined ? Ok(item) : Err("Not found")
* }
*
* const list = [1, 2, 3, 4, 5]
*
* let has_inspected = false
*
* let x = get(list, 9).inspect_err((_e) => {
* has_inspected = true
* })
*
* assert_eq!(x, Err("Not found"))
* assert_eq!(has_inspected, true)
*/
inspect_err(f: (err: E) => void): Result<T, E>;
/**
* @since 0.4.0-alpha
*
* Returns `true` if the result is `Err`.
*
* @example
*
* let x: Result<number, string>
*
* x = Ok(42)
* assert_eq!(x.is_err(), false)
*
* x = Err("Not found")
* assert_eq!(x.is_err(), true)
*/
is_err(): boolean;
/**
* @since 0.4.0-alpha
*
* Returns `true` if the result is `Err` and the value inside of it matches a predicate.
*
* @example
*
* let x: Result<{ html: string }, { statusCode: number }>
*
* x = Err({ statusCode: 500 })
* assert_eq!(
* x.is_err_and((err) => err.statusCode === 404),
* false,
* )
*
* x = Err({ statusCode: 404 })
* assert_eq!(
* x.is_err_and((err) => err.statusCode === 404),
* true,
* )
*
* x = Ok({ html: "value" })
* assert_eq!(
* x.is_err_and((err) => err.statusCode === 404),
* false,
* )
*/
is_err_and(f: (err: E) => boolean): boolean;
/**
* @since 0.4.0-alpha
*
* Returns `true` if the result is `Ok`.
*
* @example
*
* let x: Result<number, string>
*
* x = Ok(42)
* assert_eq!(x.is_ok(), true)
*
* x = Err("Not found")
* assert_eq!(x.is_ok(), false)
*/
is_ok(): boolean;
/**
* @since 0.4.0-alpha
*
* Returns `true` if the result is `Ok` and the value inside of it matches a predicate.
*
* @example
*
* let x: Result<number, string>
*
* x = Ok(0)
* assert_eq!(
* x.is_ok_and((value) => value > 10),
* false,
* )
*
* x = Ok(42)
* assert_eq!(
* x.is_ok_and((value) => value > 10),
* true,
* )
*
* x = Err("Not found")
* assert_eq!(
* x.is_ok_and((value) => value > 10),
* false,
* )
*/
is_ok_and(f: (value: T) => boolean): boolean;
/**
* @since 0.4.0-alpha
*
* Maps a `Result<T, E>` to `Result<U, E>` by applying a function
* to a contained `Ok` value, leaving an `Err` value untouched.
*
* This function can be used to compose the results of two functions.
*
* @example
*
* let x: Result<string, { statusCode: number }>
*
* x = Ok("42")
* assert_eq!(
* x.map((value) => Number.parseInt(value, 10)),
* Ok(42),
* )
*
* x = Err({ statusCode: 404 })
* assert_eq!(
* x.map((value) => Number.parseInt(value, 10)),
* Err({ statusCode: 404 }),
* )
*/
map<U>(f: (value: T) => U): Result<T | U, E>;
/**
* @since 0.4.0-alpha
*
* Returns the provided default (if `Err`),
* or applies a function to the contained value (if `Ok`).
*
* Arguments passed to `map_or` are eagerly evaluated;
* if you are passing the result of a function call,
* it is recommended to use `map_or_else`, which is lazily evaluated.
*
* @example
*
* let x: Result<string, string>
*
* x = Ok("foo")
* assert_eq!(
* x.map_or(42, (v) => v.length),
* 3,
* )
*
* x = Err("bar")
* assert_eq!(
* x.map_or(42, (v) => v.length),
* 42,
* )
*/
map_or<U>(default_value: U, f: (value: T) => U): U;
/**
* @since 0.4.0-alpha
*
* Maps a `Result<T, E>` to `U` by applying fallback function `default_f`
* to a contained `Err` value, or function `f` to a contained `Ok` value.
*
* @example
*
* const k = 21
* let x: Result<string, string>
*
* x = Ok("foo")
* assert_eq!(
* x.map_or_else(
* () => 2 * k,
* (v) => v.length,
* ),
* 3,
* )
*
* x = Err("bar")
* assert_eq!(
* x.map_or_else(
* () => 2 * k,
* (v) => v.length,
* ),
* 42,
* )
*/
map_or_else<U>(default_f: () => U, f: (value: T) => U): U;
// TODO: public ok() {}
/**
* @since 0.4.0-alpha
*
* Returns `res` if the result is `Err`, otherwise returns the `Ok` value.
*
* Arguments passed to or are eagerly evaluated;
* if you are passing the result of a function call,
* it is recommended to use `or_else`, which is lazily evaluated.
*
* @example
*
* let x: Result<number, string>
* let y: Result<number, string>
*
* x = Ok(2)
* y = Err("Not found")
* assert_eq!(x.or(y), Ok(2))
*
* x = Err("Not found")
* y = Ok(100)
* assert_eq!(x.or(y), Ok(100))
*
* x = Ok(2)
* y = Ok(100)
* assert_eq!(x.or(y), Ok(2))
*
* x = Err("Not found")
* y = Err("Not found")
* assert_eq!(x.or(y), Err("Not found"))
*/
or(res: Result<T, E>): Result<T, E>;
/**
* @since 0.4.0-alpha
*
* Calls `f` if the result is `Err`, otherwise returns the `Ok` value.
*
* This function can be used for control flow based on result values.
*
* @example
*
* let x: Result<string, { statusCode: number }>
* let y: Result<string, { statusCode: number }>
*
* x = Ok("barbarians")
* y = Ok("vikings")
* assert_eq!(
* x.or_else(() => y),
* Ok("barbarians"),
* )
*
* x = Err({ statusCode: 404 })
* y = Ok("vikings")
* assert_eq!(
* x.or_else(() => y),
* Ok("vikings"),
* )
*
* x = Err({ statusCode: 404 })
* y = Err({ statusCode: 404 })
* assert_eq!(
* x.or_else(() => y),
* Err({ statusCode: 404 }),
* )
*/
or_else(f: () => Result<T, E>): Result<T, E>;
/**
* @since 0.4.0-alpha
*
* @ignore
*
* Returns a string representing this object.
* This method is meant to be overridden by derived JS objects
* for custom type coercion logic.
*
* @example
*
* let x: Result<unknown, unknown>
*
* x = Ok(true)
* assert_eq!(x.toString(), "Ok(true)")
*
* x = Ok(42)
* assert_eq!(x.toString(), "Ok(42)")
*
* x = Ok("hello")
* assert_eq!(x.toString(), "Ok(hello)")
*
* x = Ok([1, 2])
* assert_eq!(x.toString(), "Ok(1,2)")
*
* x = Ok({})
* assert_eq!(x.toString(), "Ok([object Object])")
*
* x = Ok(() => 2 * 4)
* assert_eq!(x.toString(), "Ok(() => 2 * 4)")
*
* x = Err(true)
* assert_eq!(x.toString(), "Err(true)")
*
* x = Err(42)
* assert_eq!(x.toString(), "Err(42)")
*
* x = Err("hello")
* assert_eq!(x.toString(), "Err(hello)")
*
* x = Err([1, 2])
* assert_eq!(x.toString(), "Err(1,2)")
*
* x = Err({})
* assert_eq!(x.toString(), "Err([object Object])")
*
* x = Err(() => 2 * 4)
* assert_eq!(x.toString(), "Err(() => 2 * 4)")
*/
toString(): string;
// TODO: public transpose() {}
/**
* @since 0.4.0-alpha
*
* Returns the contained `Ok` value.
*
* Because this function may throw, its use is generally discouraged.
* Prefer to call inside `try/catch` statement, or handle the `Err` case explicitly,
* or call `unwrap_or`, `unwrap_or_else`, or `unwrap_or_default`.
*
* @throws Panics if the value is an `Err`, with a message provided by the `Err`’s value.
*
* @example
*
* let x: Result<number, string>
*
* x = Ok(42)
* assert_eq!(x.unwrap(), 42)
*
* x = Err("Not found")
* assert_err!(
* () => x.unwrap(),
* TypeError,
* "Called Result.unwrap() on an Err(E) value",
* )
*/
unwrap(): T;
/**
* @since 0.4.0-alpha
*
* Returns the contained `Err` value.
*
* @throws Panics if the value is an `Ok`, with a custom panic message provided by the `Ok`’s value.
*
* @example
*
* let x: Result<number, string>
*
* x = Ok(42)
* assert_err!(
* () => x.unwrap_err(),
* TypeError,
* "Called Result.unwrap_err() on an Ok value",
* )
*
* x = Err("Not found")
* assert_eq!(x.unwrap_err(), "Not found")
*/
unwrap_err(): E;
/**
* @since 0.4.0-alpha
*
* Returns the contained `Ok` value or a provided default.
*
* Arguments passed to `unwrap_or` are eagerly evaluated;
* if you are passing the result of a function call,
* it is recommended to use `unwrap_or_else`, which is lazily evaluated.
*
* @example
*
* let x: Result<number, string>;
*
* x = Ok(42);
* assert_eq!(x.unwrap_or(0), 42);
*
* x = Err("Not found");
* assert_eq!(x.unwrap_or(0), 0);
*/
unwrap_or(default_value: T): T;
/**
* @since 0.4.0-alpha
*
* Returns the contained `Ok` value or computes it from a closure.
*
* Useful for expensive default computations.
*
* @example
*
* let x: Result<number, string>;
*
* x = Ok(42);
* assert_eq!(
* x.unwrap_or_else((err) => err.length),
* 42,
* );
*
* x = Err("foo");
* assert_eq!(
* x.unwrap_or_else((err) => err.length),
* 3,
* );
*/
unwrap_or_else(f: (err: E) => T): T;
}