Releases: vitalics/rslike
@rslike/std@3.3.0
Minor Changes
-
2c89d8f: fix(std): correct Rust semantic mismatches in Option, Result, and match; add Option.take()
fix(result):
isErrAndalways passedundefinedto the predicate instead of the actual errorThe predicate referenced a non-existent field
this.err; the real field isthis.error.Before:
const res = predicate(this.err as TErr); // always undefined
After:
const res = predicate(this.error as TErr);
fix(result):
expect()silently returnednullwhenreasonwas an empty stringThe
reason &&short-circuit causedErr("x").expect("")to skip the throw entirely and
returnnull. Rust'sexpectalways panics onErrregardless of the message content.Before:
if (reason && this.status === Status.Err) { throw new Error(reason, { cause: this.error }); } // Err("x").expect("") → returned null silently
After:
if (this.status === Status.Err) { throw new Error(reason, { cause: this.error }); } // Err("x").expect("") → throws Error("")
fix(result):
Result.fromPromiseproduced a different type thanAsync()Async()returnsResult<Option<T>, E>.fromPromisereturnedResult<T, E>with noOption
wrapper, making the two Promise-to-Result helpers type-incompatible even though they are
documented as equivalent.Before:
const a = await Async(Promise.resolve(42)); a.unwrap().unwrap(); // 42 — Option wrapper present const b = await Result.fromPromise(Promise.resolve(42)); b.unwrap(); // 42 — no Option wrapper (inconsistent)
After:
const b = await Result.fromPromise(Promise.resolve(42)); b.unwrap().unwrap(); // 42 — Option wrapper now present, consistent with Async()
fix(option):
xor()returnedSomewhen both operands wereSomeRust's
xorreturnsSomeonly if exactly one of the two operands isSome. When both are
Somethe result must beNone. The missing check caused the wrong value to be returned.Before:
Some(1).xor(Some(2)); // → Some(1) ❌ should be None() Some(1).xor(None()); // → Some(1) ✅ None().xor(Some(2)); // → Some(2) ✅ None().xor(None()); // → None() ✅
After:
Some(1).xor(Some(2)); // → None() ✅ Some(1).xor(None()); // → Some(1) ✅ None().xor(Some(2)); // → Some(2) ✅ None().xor(None()); // → None() ✅
fix(option):
flatten()relied on accidentalSome(undefined) → Nonecoercion for theNonepathNone().flatten()produced the correct result only becauseSome(undefined)happens to coerce
toNone. An explicitisNone()guard now makes the intent clear and removes the fragile
dependency on the coercion side-effect.Before:
flatten() { if (this.value instanceof Option) { return Some(this.value.value) as never; // accessed private .value directly } return Some(this.value) as never; // None path: Some(undefined) → None by accident }
After:
flatten() { if (this.isNone()) return None() as never; // explicit, intentional if (this.value instanceof Option) { return Some((this.value as Option<any>).valueOf()) as never; } return Some(this.value) as never; }
fix(match): JSDoc comment claimed
Ok(None())triggers the Ok callback — code does the oppositeThe implementation correctly routes
Ok(None())to the Err/None callback (absence of value
inside an Ok wrapper = effectively None). Only the doc comment was wrong.Before:
Ok(None) - will trigger Ok callbackAfter:
Ok(None()) - will trigger Err/None callback
feat(option): add missing
take()methodRust's
Option::takemoves the value out of the option, leavingNonein its place. This
method was absent from the implementation.Before:
// method did not exist — runtime error Some(2).take(); // TypeError: Some(...).take is not a function
After:
const x = Some(2); const y = x.take(); x.isNone(); // true — original is now None y.unwrap(); // 2 — taken value is preserved const a = None<number>(); const b = a.take(); a.isNone(); // true b.isNone(); // true
@rslike/iter@1.0.0
@rslike/dbg@3.2.0
Minor Changes
-
2c89d8f: feat(dbg): add automatic Proxy detection and expose
isProxyutilityfeat(dbg): intercept global
Proxyconstructor to track all created proxiesOn module import,
@rslike/dbgreplaces the globalProxyconstructor with a transparent
intercepting version that registers everynew Proxy(...)andProxy.revocable(...)call in a
WeakSet. No user-side changes are required — any proxy created after the module is first
imported is automatically tracked.Before:
import { dbg } from "@rslike/dbg"; const store = new Proxy({ count: 0 }, {}); dbg(() => store); // dbg | store: {"count":0} // — no indication that `store` is a Proxy
After:
import { dbg } from "@rslike/dbg"; const store = new Proxy({ count: 0 }, {}); dbg(() => store); // dbg | store (Proxy): {"count":0} // — Proxy is detected and annotated automatically
feat(dbg): expose
isProxy(value)utility functionReturns
trueif the value was created vianew Proxy(...)after@rslike/dbgwas imported.
Returnsfalsefor plain objects, primitives, or proxies created before the module was loaded.Before:
// no way to check programmaticallyAfter:
import { isProxy } from "@rslike/dbg"; const p = new Proxy({ x: 1 }, {}); isProxy(p); // true isProxy({ x: 1 }); // false isProxy(null); // false isProxy(42); // false
feat(dbg):
dbg()return value now includesisProxyfieldThe inspection result object returned by
dbg()now exposes whether the inspected value is a
known Proxy, allowing callers to branch on it programmatically.Before:
const result = dbg(() => store); // result = { name, type, value, message, delimiter, prefix }
After:
const result = dbg(() => store); // result = { name, type, value, message, delimiter, prefix, isProxy: true } result.isProxy; // true for Proxy values, false for plain values
fix(dbg): label extraction regex stripped
() =>only with exact spacingThe old regex
/(\(\) => )/grequired a space before and after=>. Bundlers such as esbuild
and swc emit()=>without spaces, causing the arrow prefix to appear in the output label.Before:
dbg(() => double(21)); // dbg | ()=>double(21): 42 ❌ prefix not stripped
After:
dbg(() => double(21)); // dbg | double(21): 42 ✅
@rslike/cmp@3.2.1
Patch Changes
-
2c89d8f: test(cmp): add missing branch coverage for primitives and utils
test(cmp/primitives): cover
Symbol.equalsandSymbol.partialEqualson all primitive typesAdded tests for previously untested branches on
Number,String,Boolean, andDate
prototype extensions:Number[Symbol.equals]strict equality and inequalityNumber[Symbol.partialEquals]loose equality with coercionString[Symbol.equals]inequality pathString[Symbol.partialEquals]cross-type comparison via==Boolean[Symbol.equals]with plain boolean literalsBoolean[Symbol.partialEquals]withundefined(returnsfalse)Date[Symbol.compare]with ISO string argument (greater / less paths)Date[Symbol.compare]with invalid date string → throwsUndefinedBehaviorError
test(cmp/utils): document known source bugs discovered during coverage analysis
compare()with a validcompareFn: after validating the return type, the result is never
returned — execution falls through to throwUndefinedBehaviorError. Test documents this as a
known source bug.partialEquals(null, ...): no null guard beforea[kPartialEquals], causing
TypeError: Cannot read properties of null. Test documents this crash.partialEquals()falsy-value coercion:0 == falseand1 == truevia==fallback.equals()with two string primitives uses strict===.equals(null, null)falls through toa === b(returnstrue).
-
Updated dependencies [2c89d8f]
- @rslike/std@3.3.0
@rslike/std@3.2.0
Minor Changes
-
bb3ced8: ## Fixes
[@rslike/cmp]
- Number[Symbol.compare] is not a function error.
Before:
(9)[Symbol.compare](3); // Symbol.compare is not a function
After:
(9)[Symbol.compare](3); // works correctly now, no error
[@rslike/std]
unwraptypings now returns correct result.
NOTE: behavior is not changed, only inferred type
Before:
const a = None(); a.unwrap(); // unknown
After:
const a = None(); a.unwrap(); // never, since this throws an error
Other
- Migrate from
jesttovitest
@rslike/dbg@3.1.1
Patch Changes
-
bb3ced8: ## Fixes
[@rslike/cmp]
- Number[Symbol.compare] is not a function error.
Before:
(9)[Symbol.compare](3); // Symbol.compare is not a function
After:
(9)[Symbol.compare](3); // works correctly now, no error
[@rslike/std]
unwraptypings now returns correct result.
NOTE: behavior is not changed, only inferred type
Before:
const a = None(); a.unwrap(); // unknown
After:
const a = None(); a.unwrap(); // never, since this throws an error
Other
- Migrate from
jesttovitest
@rslike/cmp@3.2.0
Minor Changes
-
bb3ced8: ## Fixes
[@rslike/cmp]
- Number[Symbol.compare] is not a function error.
Before:
(9)[Symbol.compare](3); // Symbol.compare is not a function
After:
(9)[Symbol.compare](3); // works correctly now, no error
[@rslike/std]
unwraptypings now returns correct result.
NOTE: behavior is not changed, only inferred type
Before:
const a = None(); a.unwrap(); // unknown
After:
const a = None(); a.unwrap(); // never, since this throws an error
Other
- Migrate from
jesttovitest
Patch Changes
- Updated dependencies [bb3ced8]
- @rslike/std@3.2.0
@rslike/std@3.1.1
Patch Changes
-
b4303ba: What's new in
@rslike/std:- Improved documentation for constructor parameters for
OptionandResult. - Update types and JSDoc for
toString,valueOf,toJSONfor bothOptionandResult. - Make
Statusfrozen and readonly object instead of mutable forOptionandResult. - Improved docs for
Some,None,Ok,Errdescriptions expecial usage withinstanceofkeyword.
- Improved documentation for constructor parameters for
@rslike/cmp@3.1.1
Patch Changes
- Updated dependencies [b4303ba]
- @rslike/std@3.1.1
@rslike/std@3.1.0
Minor Changes
-
501b261: ## New Features
Result&Optionconstructors control flowFrom this version you can create
ResultorOptioninstances as Promises or by returning a value.import { Result, Option } from "@rslike/std"; // constructor control flow const result = new Result((ok, err) => { if (Math.random() > 0.5) { ok(42); } else { err("error"); } }); // return control flow const result2 = new Result(() => { if (Math.random() > 0.5) { return 42; } else { throw new Error("error"); } }); console.log(result2); // Result<42, Error> or Result<number, Error> const option = new Option((some, none) => { if (Math.random() > 0.5) { some(42); } else { none(); } }); const opt2 = new Option(() => { throw new Error("error"); }); console.log(opt2.isNone()); // true
NOTE: Async functions and
Promisereturn statements are not supported and throw an error forResultandOption.import { Result } from "@rslike/std"; // constructor control flow new Result((ok, err) => { ok(Promise.resolve(42)); // throw an error. Use `Result.fromPromise` instead }); // return control flow new Result(() => { return Promise.resolve(42); // throw an error. Use `Result.fromPromise` instead }); // return control flow new Result(async () => { return "qwe"; // throw an error. Use `Result.fromPromise` instead });
Option.fromPromise & Option.fromAsync methods
From this version you are able to create an Option from a Promise or an async function.
Fixes
- migrate
StatusforResultandOptionfromenumto object. - add assertion for passing constructor executor argument in
ResultandOption. - fix types for well known Symbols:
Symbol.split,Symbol.search,Symbol.iteratorandSymbol.asyncIterator - fix inspection output result for
ResultandOptionin node.js
Chore
- migrate from eslint to biome
- bump typescript to 5.8.2
- move typedoc in devDependencies
- bump typedoc to 0.27.9
- update nodejs version in CI
- fix lint issues
- migrate