Skip to content

Releases: option-t/option-t

v46.0.0

30 May 12:09
f651e13
Compare
Choose a tag to compare

Breaking Changes

Remove PascalCase style path #2251

They has been deprecated in v45.2.0.
Please see the release note to migrate your projects.

Documentation

  • Add docs/migration/v46.md. #2257

v45.3.0

30 May 11:47
b4daa6d
Compare
Choose a tag to compare

New Features

  • Expose unwrapOrThrowError from plain_result or plain_result/namespace. #2253

Internals

  • Migrate to snake_case import style. #2250, #2252

Documentation

  • Add the explain about thrown error to the jsdoc for unwrapOrThrowErrorForResult(). #2254

v45.2.0

30 May 10:40
4c5432c
Compare
Choose a tag to compare

New Deprecations

Deprecate old PascalCase style API paths #2242

The motivation is here (#1594).
We plan to remove the old PascalCase style path in the next major release. To migrate your code, please try to use the following codemod.

Codemod

Please run the following script by npx jscodeshift --transform <codemod_script>.mjs <target_dir> --parser ts.

// This works with jscodeshift@~0.15.2

const classic = Object.freeze({
    ClassicOption: 'classic_option',
    ClassicResult: 'classic_result',
});

const maybe = Object.freeze({
    Maybe: 'maybe',
    'Maybe/Maybe': 'maybe/maybe',
    'Maybe/and': 'maybe/and',
    'Maybe/andThen': 'maybe/and_then',
    'Maybe/andThenAsync': 'maybe/and_then_async',
    'Maybe/filter': 'maybe/filter',
    'Maybe/filterAsync': 'maybe/filter_async',
    'Maybe/inspect': 'maybe/inspect',
    'Maybe/map': 'maybe/map',
    'Maybe/mapAsync': 'maybe/map_async',
    'Maybe/mapOr': 'maybe/map_or',
    'Maybe/mapOrAsync': 'maybe/map_or_async',
    'Maybe/mapOrElse': 'maybe/map_or_else',
    'Maybe/mapOrElseAsync': 'maybe/map_or_else_async',
    'Maybe/namespace': 'maybe/namespace',
    'Maybe/okOr': 'maybe/ok_or',
    'Maybe/okOrElse': 'maybe/ok_or_else',
    'Maybe/okOrElseAsync': 'maybe/ok_or_else_async',
    'Maybe/or': 'maybe/or',
    'Maybe/orElse': 'maybe/or_else',
    'Maybe/orElseAsync': 'maybe/or_else_async',
    'Maybe/toNullable': 'maybe/to_nullable',
    'Maybe/toPlainResult': 'maybe/to_plain_result',
    'Maybe/toUndefinable': 'maybe/to_undefinable',
    'Maybe/unwrapOr': 'maybe/unwrap_or',
    'Maybe/unwrapOrElse': 'maybe/unwrap_or_else',
    'Maybe/unwrapOrElseAsync': 'maybe/unwrap_or_else_async',
    'Maybe/xor': 'maybe/xor',
    'Maybe/zip': 'maybe/zip',
    'Maybe/zipWith': 'maybe/zip_with',
    'Maybe/zipWithAsync': 'maybe/zip_with_async',
});

const nullable = Object.freeze({
    Nullable: 'nullable',
    'Nullable/Nullable': 'nullable/nullable',
    'Nullable/and': 'nullable/and',
    'Nullable/andThen': 'nullable/and_then',
    'Nullable/andThenAsync': 'nullable/and_then_async',
    'Nullable/filter': 'nullable/filter',
    'Nullable/filterAsync': 'nullable/filter_async',
    'Nullable/inspect': 'nullable/inspect',
    'Nullable/map': 'nullable/map',
    'Nullable/mapAsync': 'nullable/map_async',
    'Nullable/mapOr': 'nullable/map_or',
    'Nullable/mapOrAsync': 'nullable/map_or_async',
    'Nullable/mapOrElse': 'nullable/map_or_else',
    'Nullable/mapOrElseAsync': 'nullable/map_or_else_async',
    'Nullable/namespace': 'nullable/namespace',
    'Nullable/okOr': 'nullable/ok_or',
    'Nullable/okOrElse': 'nullable/ok_or_else',
    'Nullable/okOrElseAsync': 'nullable/ok_or_else_async',
    'Nullable/or': 'nullable/or',
    'Nullable/orElse': 'nullable/or_else',
    'Nullable/orElseAsync': 'nullable/or_else_async',
    'Nullable/toPlainResult': 'nullable/to_plain_result',
    'Nullable/toUndefinable': 'nullable/to_undefinable',
    'Nullable/unwrapOr': 'nullable/unwrap_or',
    'Nullable/unwrapOrElse': 'nullable/unwrap_or_else',
    'Nullable/unwrapOrElseAsync': 'nullable/unwrap_or_else_async',
    'Nullable/xor': 'nullable/xor',
    'Nullable/zip': 'nullable/zip',
    'Nullable/zipWith': 'nullable/zip_with',
    'Nullable/zipWithAsync': 'nullable/zip_with_async',
});

const plainOption = Object.freeze({
    PlainOption: 'plain_option',
    'PlainOption/Option': 'plain_option/option',
    'PlainOption/and': 'plain_option/and',
    'PlainOption/andThen': 'plain_option/and_then',
    'PlainOption/andThenAsync': 'plain_option/and_then_async',
    'PlainOption/asMut': 'plain_option/as_mut',
    'PlainOption/drop': 'plain_option/drop',
    'PlainOption/equal': 'plain_option/equal',
    'PlainOption/filter': 'plain_option/filter',
    'PlainOption/flatten': 'plain_option/flatten',
    'PlainOption/fromResult': 'plain_option/from_result',
    'PlainOption/inspect': 'plain_option/inspect',
    'PlainOption/map': 'plain_option/map',
    'PlainOption/mapAsync': 'plain_option/map_async',
    'PlainOption/mapOr': 'plain_option/map_or',
    'PlainOption/mapOrAsync': 'plain_option/map_or_async',
    'PlainOption/mapOrElse': 'plain_option/map_or_else',
    'PlainOption/mapOrElseAsync': 'plain_option/map_or_else_async',
    'PlainOption/namespace': 'plain_option/namespace',
    'PlainOption/okOr': 'plain_option/ok_or',
    'PlainOption/okOrElse': 'plain_option/ok_or_else',
    'PlainOption/or': 'plain_option/or',
    'PlainOption/orElse': 'plain_option/or_else',
    'PlainOption/orElseAsync': 'plain_option/or_else_async',
    'PlainOption/toNullable': 'plain_option/to_nullable',
    'PlainOption/toUndefinable': 'plain_option/to_undefinable',
    'PlainOption/transpose': 'plain_option/transpose',
    'PlainOption/unwrapOr': 'plain_option/unwrap_or',
    'PlainOption/unwrapOrElse': 'plain_option/unwrap_or_else',
    'PlainOption/unwrapOrElseAsync': 'plain_option/unwrap_or_else_async',
    'PlainOption/xor': 'plain_option/xor',
});

const plainResult = Object.freeze({
    PlainResult: 'plain_result',
    'PlainResult/Result': 'plain_result/result',
    'PlainResult/and': 'plain_result/and',
    'PlainResult/andThen': 'plain_result/and_then',
    'PlainResult/andThenAsync': 'plain_result/and_then_async',
    'PlainResult/asMut': 'plain_result/as_mut',
    'PlainResult/drop': 'plain_result/drop',
    'PlainResult/equal': 'plain_result/equal',
    'PlainResult/flatten': 'plain_result/flatten',
    'PlainResult/fromPromiseSettledResult': 'plain_result/from_promise_settled_result',
    'PlainResult/inspect': 'plain_result/inspect',
    'PlainResult/isErrAnd': 'plain_result/is_err_and',
    'PlainResult/isOkAnd': 'plain_result/is_ok_and',
    'PlainResult/map': 'plain_result/map',
    'PlainResult/mapAsync': 'plain_result/map_async',
    'PlainResult/mapErr': 'plain_result/map_err',
    'PlainResult/mapErrAsync': 'plain_result/map_err_async',
    'PlainResult/mapOr': 'plain_result/map_or',
    'PlainResult/mapOrAsync': 'plain_result/map_or_async',
    'PlainResult/mapOrElse': 'plain_result/map_or_else',
    'PlainResult/mapOrElseAsync': 'plain_result/map_or_else_async',
    'PlainResult/namespace': 'plain_result/namespace',
    'PlainResult/or': 'plain_result/or',
    'PlainResult/orElse': 'plain_result/or_else',
    'PlainResult/orElseAsync': 'plain_result/or_else_async',
    'PlainResult/toNullable': 'plain_result/to_nullable',
    'PlainResult/toUndefinable': 'plain_result/to_undefinable',
    'PlainResult/transpose': 'plain_result/transpose',
    'PlainResult/tryCatch': 'plain_result/try_catch',
    'PlainResult/tryCatchAsync': 'plain_result/try_catch_async',
    'PlainResult/unwrapOr': 'plain_result/unwrap_or',
    'PlainResult/unwrapOrElse': 'plain_result/unwrap_or_else',
    'PlainResult/unwrapOrElseAsync': 'plain_result/unwrap_or_else_async',
    'PlainResult/unwrapOrThrowError': 'plain_result/unwrap_or_throw_error',
});

const undefinable = Object.freeze({
    Undefinable: 'undefinable',
    'Undefinable/Undefinable': 'undefinable/undefinable',
    'Undefinable/and': 'undefinable/and',
    'Undefinable/andThen': 'undefinable/and_then',
    'Undefinable/andThenAsync': 'undefinable/and_then_async',
    'Undefinable/filter': 'undefinable/filter',
    'Undefinable/filterAsync': 'undefinable/filter_async',
    'Undefinable/inspect': 'undefinable/inspect',
    'Undefinable/map': 'undefinable/map',
    'Undefinable/mapAsync': 'undefinable/map_async',
    'Undefinable/mapOr': 'undefinable/map_or',
    'Undefinable/mapOrAsync': 'undefinable/map_or_async',
    'Undefinable/mapOrElse': 'undefinable/map_or_else',
    'Undefinable/mapOrElseAsync': 'undefinable/map_or_else_async',
    'Undefinable/namespace': 'undefinable/namespace',
    'Undefinable/okOr': 'undefinable/ok_or',
    'Undefinable/okOrElse': 'undefinable/ok_or_else',
    'Undefinable/okOrElseAsync': 'undefinable/ok_or_else_async',
    'Undefinable/or': 'undefinable/or',
    'Undefinable/orElse': 'undefinable/or_else',
    'Undefinable/orElseAsync': 'undefinable/or_else_async',
    'Undefinable/toNullable': 'undefinable/to_nullable',
    'Undefinable/toPlainResult': 'undefinable/to_plain_result',
    'Undefinable/unwrapOr': 'undefinable/unwrap_or',
    'Undefinable/unwrapOrElse': 'undefinable/unwrap_or_else',
    'Undefinable/unwrapOrElseAsync': 'undefinable/unwrap_or_else_async',
    'Undefinable/xor': 'undefinable/xor',
    'Undefinable/zip': 'undefinable/zip',
    'Undefinable/zipWith': 'undefinable/zip_with',
    'Undefinable/zipWithAsync': 'undefinable/zip_with_async',
});

const testcaseTable = {
    ...classic,
    ...maybe,
    ...nullable,
    ...plainOption,
    ...plainResult,
    ...undefinable,
};

const map = new Map(
    Object.entries(testcaseTable).map(([oldPath, newPath]) => {
        return [`option-t/${oldPath}`, `option-t/${newPath}`];
    })
);

export const parser = 'tsx';

export default function transformer(fileInfo, api) {
    const j = api.jscodeshift;
    const root = j(fileInfo.source);

    for (const [oldPath, newPath] of map) {
        const isDeprecatedPath = (path) => {
            const source = path.value.source;
            if (!source) {
                return false;
            }

            const ok = source.value === oldPath;
            return ok;
        };

        for (const d of [j.ImportDeclaration, j.ExportAllDeclaration, j.ExportNamedDeclaration]) {
            root.find(d)
                .filter(isDeprecatedPath)
                .find(j.Literal)
                .filter((path) => path.name === 'source')
                .replaceWith((path) => {
                    return j.literal(newPath);
                });
        }
    }

    return root.toSource();
}

Documentations.

  • Update ex...
Read more

v45.1.0

12 May 12:40
aac82f2
Compare
Choose a tag to compare

New Feature

Experimental

These are still under experimental and unstable. We might change this path and exposed items from here without any breaking change.

  • Add snake_case variants for all subpaths. #2241
    • When we withdraw this experiment, we'll provides a codemod to back to the previous style.

Documentation

  • Add v42~v45 release notes to docs/migration/README.md. #2240

v45.0.0

11 May 20:20
4459460
Compare
Choose a tag to compare

Breaking Changes

Make types both Err.val & Ok.err to null. #2205

This breaking change does not affect for plain JavaScript code.
This change only affects TypeScript user code.

For this library side, this fixes the long standing issue about mismatching between actual value and types.
For user side, typescript compiler causes a compile error in the place passing a value generated from different version of option-t (~v44) to the current one (v45).

Migration Path

case 1. Update all option-t dependencies (best)

case 2. Use package manager's package alias feature to make a compat bridge them.

E.g.

  • npm install option-t44@npm:option-t@^44
  • pnpm add option-t44@npm:option-t@^44
import { type Result, createOk, createErr } from 'option-t/PlainResult';
import { Result as OldResult } from 'option-t44/PlainResult/namespace';

export function bridge<T, E>(old: OldResult.Result<T, E>): Result<T, E> {
    if (OldResult.isOk(old)) {
        const val: T = OldResult.unwrapOk(old);
        return createOk<T>(val);
    } else {
        const error: E = OldResult.unwrapErr(old);
        return createErr<E>(error);
    }
}

Use ES2020 as our ESM format. #2239

Please update your toolchains (including module bundler) to latest version that supports ES2020 syntax.

v44.0.0

11 May 18:24
be06130
Compare
Choose a tag to compare

Breaking Changes

Export <TypeName> namespace module object only from <TypeName>/namespace. #2235

Please migrate your code as following:

- import * as Nullable from 'option-t/Nullable/namespace';
+ import { Nullable } from 'option-t/Nullable/namespace';

Internals

  • Use same module structure for ./PlainOption/namespace. #2234
  • Stop export * as ns syntax. #2236
  • Add why we don't export self type as Type from <TypeName>/namespace. #2233Add why we don't export self type as Type from <TypeName>/namespace. #2233

v43.2.1

11 May 17:00
d335316
Compare
Choose a tag to compare

Bug Fix

Experiments

  • ./Nullable/ns should export items as Nullable. #2229

Internals

  • Deduplicate namespace exporting. #2230
  • Use deep equal to test exported items. #2231

v43.2.0

11 May 16:09
e2699fd
Compare
Choose a tag to compare

New Features

Experiments

These are still under experimental and unstable. We might change this path and exposed items from here without any breaking change.

  • Remove Result.ok() & Result.err() from PlainOption/ns. #2227
  • Implement ./{Maybe, Nullable, Undefinable}/ns as experimental API`. #2227

v43.1.0

11 May 14:19
0dee728
Compare
Choose a tag to compare

New Features

  • Implement ./PlainResult/experimental_ns. #2225
    • This is an experiment for #2173.
    • This path is still experimental and unstable. We might change this path and exposed items from here without breaking change.

v43.0.1

08 May 21:22
413480d
Compare
Choose a tag to compare

Internals

  • Update dependencies.
  • Update pnpm to 9.1.0. #2223
  • Update pnpm-lock.yaml to v9 format. #2217
  • Cleanup unused test codes. #2214

Documentation

  • Add the comment that not to recommend to implement PlainResult.{Ok, Err} for your types. #2213
  • Add the mention about Effect-TS to "Related works" section. #2216