@clayroach/effect 3.19.14-source-capture.8 → 3.19.14-source-trace.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SourceLocation/package.json +6 -0
- package/dist/cjs/Effect.js +2 -28
- package/dist/cjs/Effect.js.map +1 -1
- package/dist/cjs/FiberRef.js +12 -1
- package/dist/cjs/FiberRef.js.map +1 -1
- package/dist/cjs/Layer.js +2 -24
- package/dist/cjs/Layer.js.map +1 -1
- package/dist/cjs/RuntimeFlags.js +1 -29
- package/dist/cjs/RuntimeFlags.js.map +1 -1
- package/dist/cjs/SourceLocation.js +60 -0
- package/dist/cjs/SourceLocation.js.map +1 -0
- package/dist/cjs/Tracer.js +1 -15
- package/dist/cjs/Tracer.js.map +1 -1
- package/dist/cjs/Utils.js +1 -1
- package/dist/cjs/Utils.js.map +1 -1
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/internal/clock.js +1 -1
- package/dist/cjs/internal/clock.js.map +1 -1
- package/dist/cjs/internal/core.js +17 -50
- package/dist/cjs/internal/core.js.map +1 -1
- package/dist/cjs/internal/effect/circular.js +18 -30
- package/dist/cjs/internal/effect/circular.js.map +1 -1
- package/dist/cjs/internal/fiberRuntime.js +16 -65
- package/dist/cjs/internal/fiberRuntime.js.map +1 -1
- package/dist/cjs/internal/layer/circular.js +1 -5
- package/dist/cjs/internal/layer/circular.js.map +1 -1
- package/dist/cjs/internal/layer.js +1 -3
- package/dist/cjs/internal/layer.js.map +1 -1
- package/dist/cjs/internal/logger.js +25 -2
- package/dist/cjs/internal/logger.js.map +1 -1
- package/dist/cjs/internal/runtimeFlags.js +2 -11
- package/dist/cjs/internal/runtimeFlags.js.map +1 -1
- package/dist/cjs/internal/tracer.js +1 -114
- package/dist/cjs/internal/tracer.js.map +1 -1
- package/dist/dts/Config.d.ts +2 -2
- package/dist/dts/Config.d.ts.map +1 -1
- package/dist/dts/Effect.d.ts +8 -29
- package/dist/dts/Effect.d.ts.map +1 -1
- package/dist/dts/FiberRef.d.ts +12 -0
- package/dist/dts/FiberRef.d.ts.map +1 -1
- package/dist/dts/Layer.d.ts +0 -22
- package/dist/dts/Layer.d.ts.map +1 -1
- package/dist/dts/RuntimeFlags.d.ts +0 -28
- package/dist/dts/RuntimeFlags.d.ts.map +1 -1
- package/dist/dts/SourceLocation.d.ts +88 -0
- package/dist/dts/SourceLocation.d.ts.map +1 -0
- package/dist/dts/Tracer.d.ts +0 -15
- package/dist/dts/Tracer.d.ts.map +1 -1
- package/dist/dts/index.d.ts +6 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/internal/core.d.ts.map +1 -1
- package/dist/dts/internal/layer.d.ts.map +1 -1
- package/dist/dts/internal/runtimeFlags.d.ts.map +1 -1
- package/dist/esm/Effect.js +0 -26
- package/dist/esm/Effect.js.map +1 -1
- package/dist/esm/FiberRef.js +11 -0
- package/dist/esm/FiberRef.js.map +1 -1
- package/dist/esm/Layer.js +0 -22
- package/dist/esm/Layer.js.map +1 -1
- package/dist/esm/RuntimeFlags.js +0 -28
- package/dist/esm/RuntimeFlags.js.map +1 -1
- package/dist/esm/SourceLocation.js +51 -0
- package/dist/esm/SourceLocation.js.map +1 -0
- package/dist/esm/Tracer.js +0 -14
- package/dist/esm/Tracer.js.map +1 -1
- package/dist/esm/Utils.js +1 -1
- package/dist/esm/Utils.js.map +1 -1
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/clock.js +1 -1
- package/dist/esm/internal/clock.js.map +1 -1
- package/dist/esm/internal/core.js +12 -45
- package/dist/esm/internal/core.js.map +1 -1
- package/dist/esm/internal/effect/circular.js +18 -30
- package/dist/esm/internal/effect/circular.js.map +1 -1
- package/dist/esm/internal/fiberRuntime.js +13 -60
- package/dist/esm/internal/fiberRuntime.js.map +1 -1
- package/dist/esm/internal/layer/circular.js +0 -4
- package/dist/esm/internal/layer/circular.js.map +1 -1
- package/dist/esm/internal/layer.js +0 -2
- package/dist/esm/internal/layer.js.map +1 -1
- package/dist/esm/internal/logger.js +25 -2
- package/dist/esm/internal/logger.js.map +1 -1
- package/dist/esm/internal/runtimeFlags.js +1 -9
- package/dist/esm/internal/runtimeFlags.js.map +1 -1
- package/dist/esm/internal/tracer.js +0 -111
- package/dist/esm/internal/tracer.js.map +1 -1
- package/package.json +12 -1
- package/src/Arbitrary.ts +1101 -0
- package/src/Array.ts +3589 -0
- package/src/BigDecimal.ts +1349 -0
- package/src/BigInt.ts +643 -0
- package/src/Boolean.ts +287 -0
- package/src/Brand.ts +360 -0
- package/src/Cache.ts +281 -0
- package/src/Cause.ts +1555 -0
- package/src/Channel.ts +2355 -0
- package/src/ChildExecutorDecision.ts +146 -0
- package/src/Chunk.ts +1495 -0
- package/src/Clock.ts +111 -0
- package/src/Config.ts +542 -0
- package/src/ConfigError.ts +270 -0
- package/src/ConfigProvider.ts +333 -0
- package/src/ConfigProviderPathPatch.ts +100 -0
- package/src/Console.ts +226 -0
- package/src/Context.ts +585 -0
- package/src/Cron.ts +706 -0
- package/src/Data.ts +596 -0
- package/src/DateTime.ts +1686 -0
- package/src/DefaultServices.ts +34 -0
- package/src/Deferred.ts +301 -0
- package/src/Differ.ts +450 -0
- package/src/Duration.ts +1000 -0
- package/src/Effect.ts +14817 -0
- package/src/Effectable.ts +107 -0
- package/src/Either.ts +1040 -0
- package/src/Encoding.ts +195 -0
- package/src/Equal.ts +98 -0
- package/src/Equivalence.ts +235 -0
- package/src/ExecutionPlan.ts +308 -0
- package/src/ExecutionStrategy.ts +119 -0
- package/src/Exit.ts +467 -0
- package/src/FastCheck.ts +9 -0
- package/src/Fiber.ts +744 -0
- package/src/FiberHandle.ts +540 -0
- package/src/FiberId.ts +195 -0
- package/src/FiberMap.ts +656 -0
- package/src/FiberRef.ts +444 -0
- package/src/FiberRefs.ts +204 -0
- package/src/FiberRefsPatch.ts +105 -0
- package/src/FiberSet.ts +491 -0
- package/src/FiberStatus.ts +108 -0
- package/src/Function.ts +1222 -0
- package/src/GlobalValue.ts +53 -0
- package/src/Graph.ts +3732 -0
- package/src/GroupBy.ts +103 -0
- package/src/HKT.ts +45 -0
- package/src/Hash.ts +195 -0
- package/src/HashMap.ts +519 -0
- package/src/HashRing.ts +317 -0
- package/src/HashSet.ts +2346 -0
- package/src/Inspectable.ts +287 -0
- package/src/Iterable.ts +1119 -0
- package/src/JSONSchema.ts +1044 -0
- package/src/KeyedPool.ts +167 -0
- package/src/Layer.ts +1228 -0
- package/src/LayerMap.ts +436 -0
- package/src/List.ts +977 -0
- package/src/LogLevel.ts +285 -0
- package/src/LogSpan.ts +25 -0
- package/src/Logger.ts +702 -0
- package/src/Mailbox.ts +268 -0
- package/src/ManagedRuntime.ts +180 -0
- package/src/Match.ts +1477 -0
- package/src/MergeDecision.ts +95 -0
- package/src/MergeState.ts +172 -0
- package/src/MergeStrategy.ts +107 -0
- package/src/Metric.ts +780 -0
- package/src/MetricBoundaries.ts +69 -0
- package/src/MetricHook.ts +151 -0
- package/src/MetricKey.ts +224 -0
- package/src/MetricKeyType.ts +262 -0
- package/src/MetricLabel.ts +47 -0
- package/src/MetricPair.ts +71 -0
- package/src/MetricPolling.ts +148 -0
- package/src/MetricRegistry.ts +48 -0
- package/src/MetricState.ts +257 -0
- package/src/Micro.ts +4405 -0
- package/src/ModuleVersion.ts +18 -0
- package/src/MutableHashMap.ts +411 -0
- package/src/MutableHashSet.ts +706 -0
- package/src/MutableList.ts +297 -0
- package/src/MutableQueue.ts +227 -0
- package/src/MutableRef.ts +202 -0
- package/src/NonEmptyIterable.ts +32 -0
- package/src/Number.ts +1071 -0
- package/src/Option.ts +2170 -0
- package/src/Order.ts +373 -0
- package/src/Ordering.ts +111 -0
- package/src/ParseResult.ts +2031 -0
- package/src/PartitionedSemaphore.ts +200 -0
- package/src/Pipeable.ts +566 -0
- package/src/Pool.ts +204 -0
- package/src/Predicate.ts +1405 -0
- package/src/Pretty.ts +205 -0
- package/src/PrimaryKey.ts +23 -0
- package/src/PubSub.ts +182 -0
- package/src/Queue.ts +644 -0
- package/src/Random.ts +204 -0
- package/src/RateLimiter.ts +138 -0
- package/src/RcMap.ts +141 -0
- package/src/RcRef.ts +122 -0
- package/src/Readable.ts +93 -0
- package/src/Record.ts +1274 -0
- package/src/RedBlackTree.ts +421 -0
- package/src/Redacted.ts +144 -0
- package/src/Ref.ts +180 -0
- package/src/RegExp.ts +38 -0
- package/src/Reloadable.ts +127 -0
- package/src/Request.ts +347 -0
- package/src/RequestBlock.ts +118 -0
- package/src/RequestResolver.ts +366 -0
- package/src/Resource.ts +119 -0
- package/src/Runtime.ts +383 -0
- package/src/RuntimeFlags.ts +336 -0
- package/src/RuntimeFlagsPatch.ts +183 -0
- package/src/STM.ts +2045 -0
- package/src/Schedule.ts +2219 -0
- package/src/ScheduleDecision.ts +62 -0
- package/src/ScheduleInterval.ts +151 -0
- package/src/ScheduleIntervals.ts +122 -0
- package/src/Scheduler.ts +353 -0
- package/src/Schema.ts +10914 -0
- package/src/SchemaAST.ts +3043 -0
- package/src/Scope.ts +204 -0
- package/src/ScopedCache.ts +151 -0
- package/src/ScopedRef.ts +117 -0
- package/src/Secret.ts +88 -0
- package/src/SingleProducerAsyncInput.ts +67 -0
- package/src/Sink.ts +1461 -0
- package/src/SortedMap.ts +287 -0
- package/src/SortedSet.ts +390 -0
- package/src/SourceLocation.ts +108 -0
- package/src/Stream.ts +6468 -0
- package/src/StreamEmit.ts +136 -0
- package/src/StreamHaltStrategy.ts +123 -0
- package/src/Streamable.ts +45 -0
- package/src/String.ts +778 -0
- package/src/Struct.ts +243 -0
- package/src/Subscribable.ts +100 -0
- package/src/SubscriptionRef.ts +298 -0
- package/src/Supervisor.ts +240 -0
- package/src/Symbol.ts +29 -0
- package/src/SynchronizedRef.ts +270 -0
- package/src/TArray.ts +495 -0
- package/src/TDeferred.ts +100 -0
- package/src/TMap.ts +515 -0
- package/src/TPriorityQueue.ts +223 -0
- package/src/TPubSub.ts +200 -0
- package/src/TQueue.ts +432 -0
- package/src/TRandom.ts +129 -0
- package/src/TReentrantLock.ts +224 -0
- package/src/TRef.ts +178 -0
- package/src/TSemaphore.ts +129 -0
- package/src/TSet.ts +365 -0
- package/src/TSubscriptionRef.ts +192 -0
- package/src/Take.ts +258 -0
- package/src/TestAnnotation.ts +158 -0
- package/src/TestAnnotationMap.ts +119 -0
- package/src/TestAnnotations.ts +117 -0
- package/src/TestClock.ts +556 -0
- package/src/TestConfig.ts +47 -0
- package/src/TestContext.ts +36 -0
- package/src/TestLive.ts +53 -0
- package/src/TestServices.ts +390 -0
- package/src/TestSized.ts +55 -0
- package/src/Tracer.ts +182 -0
- package/src/Trie.ts +840 -0
- package/src/Tuple.ts +305 -0
- package/src/Types.ts +353 -0
- package/src/Unify.ts +113 -0
- package/src/UpstreamPullRequest.ts +117 -0
- package/src/UpstreamPullStrategy.ts +121 -0
- package/src/Utils.ts +809 -0
- package/src/index.ts +1568 -0
- package/src/internal/array.ts +8 -0
- package/src/internal/blockedRequests.ts +520 -0
- package/src/internal/cache.ts +733 -0
- package/src/internal/cause.ts +1050 -0
- package/src/internal/channel/channelExecutor.ts +1200 -0
- package/src/internal/channel/channelState.ts +134 -0
- package/src/internal/channel/childExecutorDecision.ts +96 -0
- package/src/internal/channel/continuation.ts +200 -0
- package/src/internal/channel/mergeDecision.ts +113 -0
- package/src/internal/channel/mergeState.ts +120 -0
- package/src/internal/channel/mergeStrategy.ts +72 -0
- package/src/internal/channel/singleProducerAsyncInput.ts +259 -0
- package/src/internal/channel/subexecutor.ts +229 -0
- package/src/internal/channel/upstreamPullRequest.ts +84 -0
- package/src/internal/channel/upstreamPullStrategy.ts +87 -0
- package/src/internal/channel.ts +2603 -0
- package/src/internal/clock.ts +95 -0
- package/src/internal/completedRequestMap.ts +9 -0
- package/src/internal/concurrency.ts +54 -0
- package/src/internal/config.ts +716 -0
- package/src/internal/configError.ts +304 -0
- package/src/internal/configProvider/pathPatch.ts +97 -0
- package/src/internal/configProvider.ts +799 -0
- package/src/internal/console.ts +153 -0
- package/src/internal/context.ts +337 -0
- package/src/internal/core-effect.ts +2293 -0
- package/src/internal/core-stream.ts +998 -0
- package/src/internal/core.ts +3189 -0
- package/src/internal/data.ts +36 -0
- package/src/internal/dataSource.ts +327 -0
- package/src/internal/dateTime.ts +1277 -0
- package/src/internal/defaultServices/console.ts +100 -0
- package/src/internal/defaultServices.ts +163 -0
- package/src/internal/deferred.ts +46 -0
- package/src/internal/differ/chunkPatch.ts +211 -0
- package/src/internal/differ/contextPatch.ts +232 -0
- package/src/internal/differ/hashMapPatch.ts +220 -0
- package/src/internal/differ/hashSetPatch.ts +176 -0
- package/src/internal/differ/orPatch.ts +311 -0
- package/src/internal/differ/readonlyArrayPatch.ts +210 -0
- package/src/internal/differ.ts +200 -0
- package/src/internal/doNotation.ts +80 -0
- package/src/internal/effect/circular.ts +895 -0
- package/src/internal/effectable.ts +131 -0
- package/src/internal/either.ts +110 -0
- package/src/internal/encoding/base64.ts +286 -0
- package/src/internal/encoding/base64Url.ts +29 -0
- package/src/internal/encoding/common.ts +51 -0
- package/src/internal/encoding/hex.ts +315 -0
- package/src/internal/errors.ts +7 -0
- package/src/internal/executionPlan.ts +114 -0
- package/src/internal/executionStrategy.ts +74 -0
- package/src/internal/fiber.ts +388 -0
- package/src/internal/fiberId.ts +267 -0
- package/src/internal/fiberMessage.ts +82 -0
- package/src/internal/fiberRefs/patch.ts +144 -0
- package/src/internal/fiberRefs.ts +297 -0
- package/src/internal/fiberRuntime.ts +3842 -0
- package/src/internal/fiberScope.ts +71 -0
- package/src/internal/fiberStatus.ts +119 -0
- package/src/internal/groupBy.ts +530 -0
- package/src/internal/hashMap/array.ts +49 -0
- package/src/internal/hashMap/bitwise.ts +32 -0
- package/src/internal/hashMap/config.ts +14 -0
- package/src/internal/hashMap/keySet.ts +8 -0
- package/src/internal/hashMap/node.ts +391 -0
- package/src/internal/hashMap.ts +586 -0
- package/src/internal/hashSet.ts +323 -0
- package/src/internal/keyedPool.ts +244 -0
- package/src/internal/layer/circular.ts +214 -0
- package/src/internal/layer.ts +1483 -0
- package/src/internal/logSpan.ts +20 -0
- package/src/internal/logger-circular.ts +24 -0
- package/src/internal/logger.ts +522 -0
- package/src/internal/mailbox.ts +561 -0
- package/src/internal/managedRuntime/circular.ts +6 -0
- package/src/internal/managedRuntime.ts +134 -0
- package/src/internal/matcher.ts +652 -0
- package/src/internal/metric/boundaries.ts +75 -0
- package/src/internal/metric/hook.ts +483 -0
- package/src/internal/metric/key.ts +167 -0
- package/src/internal/metric/keyType.ts +238 -0
- package/src/internal/metric/label.ts +41 -0
- package/src/internal/metric/pair.ts +48 -0
- package/src/internal/metric/polling.ts +149 -0
- package/src/internal/metric/registry.ts +187 -0
- package/src/internal/metric/state.ts +290 -0
- package/src/internal/metric.ts +577 -0
- package/src/internal/opCodes/cause.ts +35 -0
- package/src/internal/opCodes/channel.ts +83 -0
- package/src/internal/opCodes/channelChildExecutorDecision.ts +17 -0
- package/src/internal/opCodes/channelMergeDecision.ts +11 -0
- package/src/internal/opCodes/channelMergeState.ts +17 -0
- package/src/internal/opCodes/channelMergeStrategy.ts +11 -0
- package/src/internal/opCodes/channelState.ts +23 -0
- package/src/internal/opCodes/channelUpstreamPullRequest.ts +11 -0
- package/src/internal/opCodes/channelUpstreamPullStrategy.ts +11 -0
- package/src/internal/opCodes/config.ts +65 -0
- package/src/internal/opCodes/configError.ts +35 -0
- package/src/internal/opCodes/continuation.ts +11 -0
- package/src/internal/opCodes/deferred.ts +11 -0
- package/src/internal/opCodes/effect.ts +89 -0
- package/src/internal/opCodes/layer.ts +59 -0
- package/src/internal/opCodes/streamHaltStrategy.ts +23 -0
- package/src/internal/option.ts +80 -0
- package/src/internal/pool.ts +432 -0
- package/src/internal/pubsub.ts +1762 -0
- package/src/internal/query.ts +204 -0
- package/src/internal/queue.ts +766 -0
- package/src/internal/random.ts +161 -0
- package/src/internal/rateLimiter.ts +93 -0
- package/src/internal/rcMap.ts +285 -0
- package/src/internal/rcRef.ts +192 -0
- package/src/internal/redBlackTree/iterator.ts +200 -0
- package/src/internal/redBlackTree/node.ts +68 -0
- package/src/internal/redBlackTree.ts +1245 -0
- package/src/internal/redacted.ts +73 -0
- package/src/internal/ref.ts +171 -0
- package/src/internal/reloadable.ts +140 -0
- package/src/internal/request.ts +177 -0
- package/src/internal/resource.ts +76 -0
- package/src/internal/ringBuffer.ts +68 -0
- package/src/internal/runtime.ts +558 -0
- package/src/internal/runtimeFlags.ts +178 -0
- package/src/internal/runtimeFlagsPatch.ts +103 -0
- package/src/internal/schedule/decision.ts +47 -0
- package/src/internal/schedule/interval.ts +101 -0
- package/src/internal/schedule/intervals.ts +180 -0
- package/src/internal/schedule.ts +2199 -0
- package/src/internal/schema/errors.ts +191 -0
- package/src/internal/schema/schemaId.ts +106 -0
- package/src/internal/schema/util.ts +50 -0
- package/src/internal/scopedCache.ts +644 -0
- package/src/internal/scopedRef.ts +118 -0
- package/src/internal/secret.ts +89 -0
- package/src/internal/singleShotGen.ts +35 -0
- package/src/internal/sink.ts +2120 -0
- package/src/internal/stack.ts +10 -0
- package/src/internal/stm/core.ts +817 -0
- package/src/internal/stm/entry.ts +59 -0
- package/src/internal/stm/journal.ts +123 -0
- package/src/internal/stm/opCodes/stm.ts +71 -0
- package/src/internal/stm/opCodes/stmState.ts +17 -0
- package/src/internal/stm/opCodes/strategy.ts +17 -0
- package/src/internal/stm/opCodes/tExit.ts +29 -0
- package/src/internal/stm/opCodes/tryCommit.ts +11 -0
- package/src/internal/stm/stm.ts +1453 -0
- package/src/internal/stm/stmState.ts +136 -0
- package/src/internal/stm/tArray.ts +550 -0
- package/src/internal/stm/tDeferred.ts +81 -0
- package/src/internal/stm/tExit.ts +190 -0
- package/src/internal/stm/tMap.ts +824 -0
- package/src/internal/stm/tPriorityQueue.ts +267 -0
- package/src/internal/stm/tPubSub.ts +551 -0
- package/src/internal/stm/tQueue.ts +393 -0
- package/src/internal/stm/tRandom.ts +140 -0
- package/src/internal/stm/tReentrantLock.ts +352 -0
- package/src/internal/stm/tRef.ts +195 -0
- package/src/internal/stm/tSemaphore.ts +113 -0
- package/src/internal/stm/tSet.ts +259 -0
- package/src/internal/stm/tSubscriptionRef.ts +286 -0
- package/src/internal/stm/tryCommit.ts +34 -0
- package/src/internal/stm/txnId.ts +14 -0
- package/src/internal/stm/versioned.ts +4 -0
- package/src/internal/stream/debounceState.ts +57 -0
- package/src/internal/stream/emit.ts +123 -0
- package/src/internal/stream/haltStrategy.ts +94 -0
- package/src/internal/stream/handoff.ts +187 -0
- package/src/internal/stream/handoffSignal.ts +59 -0
- package/src/internal/stream/pull.ts +34 -0
- package/src/internal/stream/sinkEndReason.ts +30 -0
- package/src/internal/stream/zipAllState.ts +88 -0
- package/src/internal/stream/zipChunksState.ts +56 -0
- package/src/internal/stream.ts +8801 -0
- package/src/internal/string-utils.ts +107 -0
- package/src/internal/subscriptionRef.ts +138 -0
- package/src/internal/supervisor/patch.ts +190 -0
- package/src/internal/supervisor.ts +303 -0
- package/src/internal/synchronizedRef.ts +114 -0
- package/src/internal/take.ts +199 -0
- package/src/internal/testing/sleep.ts +27 -0
- package/src/internal/testing/suspendedWarningData.ts +85 -0
- package/src/internal/testing/warningData.ts +94 -0
- package/src/internal/tracer.ts +150 -0
- package/src/internal/trie.ts +722 -0
- package/src/internal/version.ts +7 -0
package/src/Option.ts
ADDED
|
@@ -0,0 +1,2170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 2.0.0
|
|
3
|
+
*/
|
|
4
|
+
import type { Either } from "./Either.js"
|
|
5
|
+
import * as Equal from "./Equal.js"
|
|
6
|
+
import * as Equivalence from "./Equivalence.js"
|
|
7
|
+
import type { LazyArg } from "./Function.js"
|
|
8
|
+
import { constNull, constUndefined, dual, identity, isFunction } from "./Function.js"
|
|
9
|
+
import type { TypeLambda } from "./HKT.js"
|
|
10
|
+
import type { Inspectable } from "./Inspectable.js"
|
|
11
|
+
import * as doNotation from "./internal/doNotation.js"
|
|
12
|
+
import * as either from "./internal/either.js"
|
|
13
|
+
import * as option from "./internal/option.js"
|
|
14
|
+
import type { Order } from "./Order.js"
|
|
15
|
+
import * as order from "./Order.js"
|
|
16
|
+
import type { Pipeable } from "./Pipeable.js"
|
|
17
|
+
import type { Predicate, Refinement } from "./Predicate.js"
|
|
18
|
+
import type { Covariant, NoInfer, NotFunction } from "./Types.js"
|
|
19
|
+
import type * as Unify from "./Unify.js"
|
|
20
|
+
import * as Gen from "./Utils.js"
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The `Option` data type represents optional values. An `Option<A>` can either
|
|
24
|
+
* be `Some<A>`, containing a value of type `A`, or `None`, representing the
|
|
25
|
+
* absence of a value.
|
|
26
|
+
*
|
|
27
|
+
* **When to Use**
|
|
28
|
+
*
|
|
29
|
+
* You can use `Option` in scenarios like:
|
|
30
|
+
*
|
|
31
|
+
* - Using it for initial values
|
|
32
|
+
* - Returning values from functions that are not defined for all possible
|
|
33
|
+
* inputs (referred to as “partial functions”)
|
|
34
|
+
* - Managing optional fields in data structures
|
|
35
|
+
* - Handling optional function arguments
|
|
36
|
+
*
|
|
37
|
+
* @category Models
|
|
38
|
+
* @since 2.0.0
|
|
39
|
+
*/
|
|
40
|
+
export type Option<A> = None<A> | Some<A>
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @category Symbols
|
|
44
|
+
* @since 2.0.0
|
|
45
|
+
*/
|
|
46
|
+
export const TypeId: unique symbol = Symbol.for("effect/Option")
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @category Symbols
|
|
50
|
+
* @since 2.0.0
|
|
51
|
+
*/
|
|
52
|
+
export type TypeId = typeof TypeId
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @category Models
|
|
56
|
+
* @since 2.0.0
|
|
57
|
+
*/
|
|
58
|
+
export interface None<out A> extends Pipeable, Inspectable {
|
|
59
|
+
readonly _tag: "None"
|
|
60
|
+
readonly _op: "None"
|
|
61
|
+
readonly [TypeId]: {
|
|
62
|
+
readonly _A: Covariant<A>
|
|
63
|
+
}
|
|
64
|
+
[Unify.typeSymbol]?: unknown
|
|
65
|
+
[Unify.unifySymbol]?: OptionUnify<this>
|
|
66
|
+
[Unify.ignoreSymbol]?: OptionUnifyIgnore
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @category Models
|
|
71
|
+
* @since 2.0.0
|
|
72
|
+
*/
|
|
73
|
+
export interface Some<out A> extends Pipeable, Inspectable {
|
|
74
|
+
readonly _tag: "Some"
|
|
75
|
+
readonly _op: "Some"
|
|
76
|
+
readonly value: A
|
|
77
|
+
readonly [TypeId]: {
|
|
78
|
+
readonly _A: Covariant<A>
|
|
79
|
+
}
|
|
80
|
+
[Unify.typeSymbol]?: unknown
|
|
81
|
+
[Unify.unifySymbol]?: OptionUnify<this>
|
|
82
|
+
[Unify.ignoreSymbol]?: OptionUnifyIgnore
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @category Models
|
|
87
|
+
* @since 2.0.0
|
|
88
|
+
*/
|
|
89
|
+
export interface OptionUnify<A extends { [Unify.typeSymbol]?: any }> {
|
|
90
|
+
Option?: () => A[Unify.typeSymbol] extends Option<infer A0> | infer _ ? Option<A0> : never
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @since 2.0.0
|
|
95
|
+
*/
|
|
96
|
+
export declare namespace Option {
|
|
97
|
+
/**
|
|
98
|
+
* Extracts the type of the value contained in an `Option`.
|
|
99
|
+
*
|
|
100
|
+
* **Example** (Getting the Value Type of an Option)
|
|
101
|
+
*
|
|
102
|
+
* ```ts
|
|
103
|
+
* import { Option } from "effect"
|
|
104
|
+
*
|
|
105
|
+
* // Declare an Option holding a string
|
|
106
|
+
* declare const myOption: Option.Option<string>
|
|
107
|
+
*
|
|
108
|
+
* // Extract the type of the value within the Option
|
|
109
|
+
* //
|
|
110
|
+
* // ┌─── string
|
|
111
|
+
* // ▼
|
|
112
|
+
* type MyType = Option.Option.Value<typeof myOption>
|
|
113
|
+
* ```
|
|
114
|
+
*
|
|
115
|
+
* @since 2.0.0
|
|
116
|
+
* @category Type-level Utils
|
|
117
|
+
*/
|
|
118
|
+
export type Value<T extends Option<any>> = [T] extends [Option<infer _A>] ? _A : never
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @category Models
|
|
123
|
+
* @since 2.0.0
|
|
124
|
+
*/
|
|
125
|
+
export interface OptionUnifyIgnore {}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* @category Type Lambdas
|
|
129
|
+
* @since 2.0.0
|
|
130
|
+
*/
|
|
131
|
+
export interface OptionTypeLambda extends TypeLambda {
|
|
132
|
+
readonly type: Option<this["Target"]>
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Represents the absence of a value by creating an empty `Option`.
|
|
137
|
+
*
|
|
138
|
+
* `Option.none` returns an `Option<never>`, which is a subtype of `Option<A>`.
|
|
139
|
+
* This means you can use it in place of any `Option<A>` regardless of the type
|
|
140
|
+
* `A`.
|
|
141
|
+
*
|
|
142
|
+
* **Example** (Creating an Option with No Value)
|
|
143
|
+
*
|
|
144
|
+
* ```ts
|
|
145
|
+
* import { Option } from "effect"
|
|
146
|
+
*
|
|
147
|
+
* // An Option holding no value
|
|
148
|
+
* //
|
|
149
|
+
* // ┌─── Option<never>
|
|
150
|
+
* // ▼
|
|
151
|
+
* const noValue = Option.none()
|
|
152
|
+
*
|
|
153
|
+
* console.log(noValue)
|
|
154
|
+
* // Output: { _id: 'Option', _tag: 'None' }
|
|
155
|
+
* ```
|
|
156
|
+
*
|
|
157
|
+
* @see {@link some} for the opposite operation.
|
|
158
|
+
*
|
|
159
|
+
* @category Constructors
|
|
160
|
+
* @since 2.0.0
|
|
161
|
+
*/
|
|
162
|
+
export const none = <A = never>(): Option<A> => option.none
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Wraps the given value into an `Option` to represent its presence.
|
|
166
|
+
*
|
|
167
|
+
* **Example** (Creating an Option with a Value)
|
|
168
|
+
*
|
|
169
|
+
* ```ts
|
|
170
|
+
* import { Option } from "effect"
|
|
171
|
+
*
|
|
172
|
+
* // An Option holding the number 1
|
|
173
|
+
* //
|
|
174
|
+
* // ┌─── Option<number>
|
|
175
|
+
* // ▼
|
|
176
|
+
* const value = Option.some(1)
|
|
177
|
+
*
|
|
178
|
+
* console.log(value)
|
|
179
|
+
* // Output: { _id: 'Option', _tag: 'Some', value: 1 }
|
|
180
|
+
* ```
|
|
181
|
+
*
|
|
182
|
+
* @see {@link none} for the opposite operation.
|
|
183
|
+
*
|
|
184
|
+
* @category Constructors
|
|
185
|
+
* @since 2.0.0
|
|
186
|
+
*/
|
|
187
|
+
export const some: <A>(value: A) => Option<A> = option.some
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Determines whether the given value is an `Option`.
|
|
191
|
+
*
|
|
192
|
+
* **Details**
|
|
193
|
+
*
|
|
194
|
+
* This function checks if a value is an instance of `Option`. It returns `true`
|
|
195
|
+
* if the value is either `Option.some` or `Option.none`, and `false` otherwise.
|
|
196
|
+
* This is particularly useful when working with unknown values or when you need
|
|
197
|
+
* to ensure type safety in your code.
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* ```ts
|
|
201
|
+
* import { Option } from "effect"
|
|
202
|
+
*
|
|
203
|
+
* console.log(Option.isOption(Option.some(1)))
|
|
204
|
+
* // Output: true
|
|
205
|
+
*
|
|
206
|
+
* console.log(Option.isOption(Option.none()))
|
|
207
|
+
* // Output: true
|
|
208
|
+
*
|
|
209
|
+
* console.log(Option.isOption({}))
|
|
210
|
+
* // Output: false
|
|
211
|
+
* ```
|
|
212
|
+
*
|
|
213
|
+
* @category Guards
|
|
214
|
+
* @since 2.0.0
|
|
215
|
+
*/
|
|
216
|
+
export const isOption: (input: unknown) => input is Option<unknown> = option.isOption
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Checks whether an `Option` represents the absence of a value (`None`).
|
|
220
|
+
*
|
|
221
|
+
* @example
|
|
222
|
+
* ```ts
|
|
223
|
+
* import { Option } from "effect"
|
|
224
|
+
*
|
|
225
|
+
* console.log(Option.isNone(Option.some(1)))
|
|
226
|
+
* // Output: false
|
|
227
|
+
*
|
|
228
|
+
* console.log(Option.isNone(Option.none()))
|
|
229
|
+
* // Output: true
|
|
230
|
+
* ```
|
|
231
|
+
*
|
|
232
|
+
* @see {@link isSome} for the opposite check.
|
|
233
|
+
*
|
|
234
|
+
* @category Guards
|
|
235
|
+
* @since 2.0.0
|
|
236
|
+
*/
|
|
237
|
+
export const isNone: <A>(self: Option<A>) => self is None<A> = option.isNone
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Checks whether an `Option` contains a value (`Some`).
|
|
241
|
+
*
|
|
242
|
+
* @example
|
|
243
|
+
* ```ts
|
|
244
|
+
* import { Option } from "effect"
|
|
245
|
+
*
|
|
246
|
+
* console.log(Option.isSome(Option.some(1)))
|
|
247
|
+
* // Output: true
|
|
248
|
+
*
|
|
249
|
+
* console.log(Option.isSome(Option.none()))
|
|
250
|
+
* // Output: false
|
|
251
|
+
* ```
|
|
252
|
+
*
|
|
253
|
+
* @see {@link isNone} for the opposite check.
|
|
254
|
+
*
|
|
255
|
+
* @category Guards
|
|
256
|
+
* @since 2.0.0
|
|
257
|
+
*/
|
|
258
|
+
export const isSome: <A>(self: Option<A>) => self is Some<A> = option.isSome
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Performs pattern matching on an `Option` to handle both `Some` and `None`
|
|
262
|
+
* cases.
|
|
263
|
+
*
|
|
264
|
+
* **Details**
|
|
265
|
+
*
|
|
266
|
+
* This function allows you to match against an `Option` and handle both
|
|
267
|
+
* scenarios: when the `Option` is `None` (i.e., contains no value), and when
|
|
268
|
+
* the `Option` is `Some` (i.e., contains a value). It executes one of the
|
|
269
|
+
* provided functions based on the case:
|
|
270
|
+
*
|
|
271
|
+
* - If the `Option` is `None`, the `onNone` function is executed and its result
|
|
272
|
+
* is returned.
|
|
273
|
+
* - If the `Option` is `Some`, the `onSome` function is executed with the
|
|
274
|
+
* contained value, and its result is returned.
|
|
275
|
+
*
|
|
276
|
+
* This function provides a concise and functional way to handle optional values
|
|
277
|
+
* without resorting to `if` or manual checks, making your code more declarative
|
|
278
|
+
* and readable.
|
|
279
|
+
*
|
|
280
|
+
* **Example** (Pattern Matching with Option)
|
|
281
|
+
*
|
|
282
|
+
* ```ts
|
|
283
|
+
* import { Option } from "effect"
|
|
284
|
+
*
|
|
285
|
+
* const foo = Option.some(1)
|
|
286
|
+
*
|
|
287
|
+
* const message = Option.match(foo, {
|
|
288
|
+
* onNone: () => "Option is empty",
|
|
289
|
+
* onSome: (value) => `Option has a value: ${value}`
|
|
290
|
+
* })
|
|
291
|
+
*
|
|
292
|
+
* console.log(message)
|
|
293
|
+
* // Output: "Option has a value: 1"
|
|
294
|
+
* ```
|
|
295
|
+
*
|
|
296
|
+
* @category Pattern matching
|
|
297
|
+
* @since 2.0.0
|
|
298
|
+
*/
|
|
299
|
+
export const match: {
|
|
300
|
+
<B, A, C = B>(options: {
|
|
301
|
+
readonly onNone: LazyArg<B>
|
|
302
|
+
readonly onSome: (a: A) => C
|
|
303
|
+
}): (self: Option<A>) => B | C
|
|
304
|
+
<A, B, C = B>(self: Option<A>, options: {
|
|
305
|
+
readonly onNone: LazyArg<B>
|
|
306
|
+
readonly onSome: (a: A) => C
|
|
307
|
+
}): B | C
|
|
308
|
+
} = dual(
|
|
309
|
+
2,
|
|
310
|
+
<A, B, C = B>(self: Option<A>, { onNone, onSome }: {
|
|
311
|
+
readonly onNone: LazyArg<B>
|
|
312
|
+
readonly onSome: (a: A) => C
|
|
313
|
+
}): B | C => isNone(self) ? onNone() : onSome(self.value)
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Converts an `Option`-returning function into a type guard.
|
|
318
|
+
*
|
|
319
|
+
* **Details**
|
|
320
|
+
*
|
|
321
|
+
* This function transforms a function that returns an `Option` into a type
|
|
322
|
+
* guard, ensuring type safety when validating or narrowing types. The returned
|
|
323
|
+
* type guard function checks whether the input satisfies the condition defined
|
|
324
|
+
* in the original `Option`-returning function.
|
|
325
|
+
*
|
|
326
|
+
* If the original function returns `Option.some`, the type guard evaluates to
|
|
327
|
+
* `true`, confirming the input is of the desired type. If the function returns
|
|
328
|
+
* `Option.none`, the type guard evaluates to `false`.
|
|
329
|
+
*
|
|
330
|
+
* This utility is especially useful for validating types in union types,
|
|
331
|
+
* filtering arrays, or ensuring safe handling of specific subtypes.
|
|
332
|
+
*
|
|
333
|
+
* @example
|
|
334
|
+
* ```ts
|
|
335
|
+
* import { Option } from "effect"
|
|
336
|
+
*
|
|
337
|
+
* type MyData = string | number
|
|
338
|
+
*
|
|
339
|
+
* const parseString = (data: MyData): Option.Option<string> =>
|
|
340
|
+
* typeof data === "string" ? Option.some(data) : Option.none()
|
|
341
|
+
*
|
|
342
|
+
* // ┌─── (a: MyData) => a is string
|
|
343
|
+
* // ▼
|
|
344
|
+
* const isString = Option.toRefinement(parseString)
|
|
345
|
+
*
|
|
346
|
+
* console.log(isString("a"))
|
|
347
|
+
* // Output: true
|
|
348
|
+
*
|
|
349
|
+
* console.log(isString(1))
|
|
350
|
+
* // Output: false
|
|
351
|
+
* ```
|
|
352
|
+
*
|
|
353
|
+
* @category Conversions
|
|
354
|
+
* @since 2.0.0
|
|
355
|
+
*/
|
|
356
|
+
export const toRefinement = <A, B extends A>(f: (a: A) => Option<B>): (a: A) => a is B => (a: A): a is B => isSome(f(a))
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Converts an `Iterable` into an `Option`, wrapping the first element if it
|
|
360
|
+
* exists.
|
|
361
|
+
*
|
|
362
|
+
* **Details**
|
|
363
|
+
*
|
|
364
|
+
* This function takes an `Iterable` (e.g., an array, a generator, or any object
|
|
365
|
+
* implementing the `Iterable` interface) and returns an `Option` based on its
|
|
366
|
+
* content:
|
|
367
|
+
*
|
|
368
|
+
* - If the `Iterable` contains at least one element, the first element is
|
|
369
|
+
* wrapped in a `Some` and returned.
|
|
370
|
+
* - If the `Iterable` is empty, `None` is returned, representing the absence of
|
|
371
|
+
* a value.
|
|
372
|
+
*
|
|
373
|
+
* This utility is useful for safely handling collections that might be empty,
|
|
374
|
+
* ensuring you explicitly handle both cases where a value exists or doesn't.
|
|
375
|
+
*
|
|
376
|
+
* @example
|
|
377
|
+
* ```ts
|
|
378
|
+
* import { Option } from "effect"
|
|
379
|
+
*
|
|
380
|
+
* console.log(Option.fromIterable([1, 2, 3]))
|
|
381
|
+
* // Output: { _id: 'Option', _tag: 'Some', value: 1 }
|
|
382
|
+
*
|
|
383
|
+
* console.log(Option.fromIterable([]))
|
|
384
|
+
* // Output: { _id: 'Option', _tag: 'None' }
|
|
385
|
+
* ```
|
|
386
|
+
*
|
|
387
|
+
* @category Constructors
|
|
388
|
+
* @since 2.0.0
|
|
389
|
+
*/
|
|
390
|
+
export const fromIterable = <A>(collection: Iterable<A>): Option<A> => {
|
|
391
|
+
for (const a of collection) {
|
|
392
|
+
return some(a)
|
|
393
|
+
}
|
|
394
|
+
return none()
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Converts an `Either` into an `Option` by discarding the error and extracting
|
|
399
|
+
* the right value.
|
|
400
|
+
*
|
|
401
|
+
* **Details**
|
|
402
|
+
*
|
|
403
|
+
* This function takes an `Either` and returns an `Option` based on its value:
|
|
404
|
+
*
|
|
405
|
+
* - If the `Either` is a `Right`, its value is wrapped in a `Some` and
|
|
406
|
+
* returned.
|
|
407
|
+
* - If the `Either` is a `Left`, the error is discarded, and `None` is
|
|
408
|
+
* returned.
|
|
409
|
+
*
|
|
410
|
+
* This is particularly useful when you only care about the success case
|
|
411
|
+
* (`Right`) of an `Either` and want to handle the result using `Option`. By
|
|
412
|
+
* using this function, you can convert `Either` into a simpler structure for
|
|
413
|
+
* cases where error handling is not required.
|
|
414
|
+
*
|
|
415
|
+
* @example
|
|
416
|
+
* ```ts
|
|
417
|
+
* import { Either, Option } from "effect"
|
|
418
|
+
*
|
|
419
|
+
* console.log(Option.getRight(Either.right("ok")))
|
|
420
|
+
* // Output: { _id: 'Option', _tag: 'Some', value: 'ok' }
|
|
421
|
+
*
|
|
422
|
+
* console.log(Option.getRight(Either.left("err")))
|
|
423
|
+
* // Output: { _id: 'Option', _tag: 'None' }
|
|
424
|
+
* ```
|
|
425
|
+
*
|
|
426
|
+
* @see {@link getLeft} for the opposite operation.
|
|
427
|
+
*
|
|
428
|
+
* @category Conversions
|
|
429
|
+
* @since 2.0.0
|
|
430
|
+
*/
|
|
431
|
+
export const getRight: <R, L>(self: Either<R, L>) => Option<R> = either.getRight
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* Converts an `Either` into an `Option` by discarding the right value and
|
|
435
|
+
* extracting the left value.
|
|
436
|
+
*
|
|
437
|
+
* **Details**
|
|
438
|
+
*
|
|
439
|
+
* This function transforms an `Either` into an `Option` as follows:
|
|
440
|
+
*
|
|
441
|
+
* - If the `Either` is a `Left`, its value is wrapped in a `Some` and returned.
|
|
442
|
+
* - If the `Either` is a `Right`, the value is discarded, and `None` is
|
|
443
|
+
* returned.
|
|
444
|
+
*
|
|
445
|
+
* This utility is useful when you only care about the error case (`Left`) of an
|
|
446
|
+
* `Either` and want to handle it as an `Option`. By discarding the right value,
|
|
447
|
+
* it simplifies error-focused workflows.
|
|
448
|
+
*
|
|
449
|
+
* @example
|
|
450
|
+
* ```ts
|
|
451
|
+
* import { Either, Option } from "effect"
|
|
452
|
+
*
|
|
453
|
+
* console.log(Option.getLeft(Either.right("ok")))
|
|
454
|
+
* // Output: { _id: 'Option', _tag: 'None' }
|
|
455
|
+
*
|
|
456
|
+
* console.log(Option.getLeft(Either.left("err")))
|
|
457
|
+
* // Output: { _id: 'Option', _tag: 'Some', value: 'err' }
|
|
458
|
+
* ```
|
|
459
|
+
*
|
|
460
|
+
* @see {@link getRight} for the opposite operation.
|
|
461
|
+
*
|
|
462
|
+
* @category Conversions
|
|
463
|
+
* @since 2.0.0
|
|
464
|
+
*/
|
|
465
|
+
export const getLeft: <R, L>(self: Either<R, L>) => Option<L> = either.getLeft
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* Returns the value contained in the `Option` if it is `Some`, otherwise
|
|
469
|
+
* evaluates and returns the result of `onNone`.
|
|
470
|
+
*
|
|
471
|
+
* **Details**
|
|
472
|
+
*
|
|
473
|
+
* This function allows you to provide a fallback value or computation for when
|
|
474
|
+
* an `Option` is `None`. If the `Option` contains a value (`Some`), that value
|
|
475
|
+
* is returned. If it is empty (`None`), the `onNone` function is executed, and
|
|
476
|
+
* its result is returned instead.
|
|
477
|
+
*
|
|
478
|
+
* This utility is helpful for safely handling `Option` values by ensuring you
|
|
479
|
+
* always receive a meaningful result, whether or not the `Option` contains a
|
|
480
|
+
* value. It is particularly useful for providing default values or alternative
|
|
481
|
+
* logic when working with optional values.
|
|
482
|
+
*
|
|
483
|
+
* @example
|
|
484
|
+
* ```ts
|
|
485
|
+
* import { Option } from "effect"
|
|
486
|
+
*
|
|
487
|
+
* console.log(Option.some(1).pipe(Option.getOrElse(() => 0)))
|
|
488
|
+
* // Output: 1
|
|
489
|
+
*
|
|
490
|
+
* console.log(Option.none().pipe(Option.getOrElse(() => 0)))
|
|
491
|
+
* // Output: 0
|
|
492
|
+
* ```
|
|
493
|
+
*
|
|
494
|
+
* @see {@link getOrNull} for a version that returns `null` instead of executing a function.
|
|
495
|
+
* @see {@link getOrUndefined} for a version that returns `undefined` instead of executing a function.
|
|
496
|
+
*
|
|
497
|
+
* @category Getters
|
|
498
|
+
* @since 2.0.0
|
|
499
|
+
*/
|
|
500
|
+
export const getOrElse: {
|
|
501
|
+
<B>(onNone: LazyArg<B>): <A>(self: Option<A>) => B | A
|
|
502
|
+
<A, B>(self: Option<A>, onNone: LazyArg<B>): A | B
|
|
503
|
+
} = dual(
|
|
504
|
+
2,
|
|
505
|
+
<A, B>(self: Option<A>, onNone: LazyArg<B>): A | B => isNone(self) ? onNone() : self.value
|
|
506
|
+
)
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Returns the provided `Option` `that` if the current `Option` (`self`) is
|
|
510
|
+
* `None`; otherwise, it returns `self`.
|
|
511
|
+
*
|
|
512
|
+
* **Details**
|
|
513
|
+
*
|
|
514
|
+
* This function provides a fallback mechanism for `Option` values. If the
|
|
515
|
+
* current `Option` is `None` (i.e., it contains no value), the `that` function
|
|
516
|
+
* is evaluated, and its resulting `Option` is returned. If the current `Option`
|
|
517
|
+
* is `Some` (i.e., it contains a value), the original `Option` is returned
|
|
518
|
+
* unchanged.
|
|
519
|
+
*
|
|
520
|
+
* This is particularly useful for chaining fallback values or computations,
|
|
521
|
+
* allowing you to provide alternative `Option` values when the first one is
|
|
522
|
+
* empty.
|
|
523
|
+
*
|
|
524
|
+
* @example
|
|
525
|
+
* ```ts
|
|
526
|
+
* import { Option } from "effect"
|
|
527
|
+
*
|
|
528
|
+
* console.log(Option.none().pipe(Option.orElse(() => Option.none())))
|
|
529
|
+
* // Output: { _id: 'Option', _tag: 'None' }
|
|
530
|
+
*
|
|
531
|
+
* console.log(Option.some("a").pipe(Option.orElse(() => Option.none())))
|
|
532
|
+
* // Output: { _id: 'Option', _tag: 'Some', value: 'a' }
|
|
533
|
+
*
|
|
534
|
+
* console.log(Option.none().pipe(Option.orElse(() => Option.some("b"))))
|
|
535
|
+
* // Output: { _id: 'Option', _tag: 'Some', value: 'b' }
|
|
536
|
+
*
|
|
537
|
+
* console.log(Option.some("a").pipe(Option.orElse(() => Option.some("b"))))
|
|
538
|
+
* // Output: { _id: 'Option', _tag: 'Some', value: 'a' }
|
|
539
|
+
* ```
|
|
540
|
+
*
|
|
541
|
+
* @category Error handling
|
|
542
|
+
* @since 2.0.0
|
|
543
|
+
*/
|
|
544
|
+
export const orElse: {
|
|
545
|
+
<B>(that: LazyArg<Option<B>>): <A>(self: Option<A>) => Option<B | A>
|
|
546
|
+
<A, B>(self: Option<A>, that: LazyArg<Option<B>>): Option<A | B>
|
|
547
|
+
} = dual(
|
|
548
|
+
2,
|
|
549
|
+
<A, B>(self: Option<A>, that: LazyArg<Option<B>>): Option<A | B> => isNone(self) ? that() : self
|
|
550
|
+
)
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Returns the provided default value wrapped in `Some` if the current `Option`
|
|
554
|
+
* (`self`) is `None`; otherwise, returns `self`.
|
|
555
|
+
*
|
|
556
|
+
* **Details**
|
|
557
|
+
*
|
|
558
|
+
* This function provides a way to supply a default value for cases where an
|
|
559
|
+
* `Option` is `None`. If the current `Option` is empty (`None`), the `onNone`
|
|
560
|
+
* function is executed to compute the default value, which is then wrapped in a
|
|
561
|
+
* `Some`. If the current `Option` contains a value (`Some`), it is returned as
|
|
562
|
+
* is.
|
|
563
|
+
*
|
|
564
|
+
* This is particularly useful for handling optional values where a fallback
|
|
565
|
+
* default needs to be provided explicitly in case of absence.
|
|
566
|
+
*
|
|
567
|
+
* @example
|
|
568
|
+
* ```ts
|
|
569
|
+
* import { Option } from "effect"
|
|
570
|
+
*
|
|
571
|
+
* console.log(Option.none().pipe(Option.orElseSome(() => "b")))
|
|
572
|
+
* // Output: { _id: 'Option', _tag: 'Some', value: 'b' }
|
|
573
|
+
*
|
|
574
|
+
* console.log(Option.some("a").pipe(Option.orElseSome(() => "b")))
|
|
575
|
+
* // Output: { _id: 'Option', _tag: 'Some', value: 'a' }
|
|
576
|
+
* ```
|
|
577
|
+
*
|
|
578
|
+
* @category Error handling
|
|
579
|
+
* @since 2.0.0
|
|
580
|
+
*/
|
|
581
|
+
export const orElseSome: {
|
|
582
|
+
<B>(onNone: LazyArg<B>): <A>(self: Option<A>) => Option<B | A>
|
|
583
|
+
<A, B>(self: Option<A>, onNone: LazyArg<B>): Option<A | B>
|
|
584
|
+
} = dual(
|
|
585
|
+
2,
|
|
586
|
+
<A, B>(self: Option<A>, onNone: LazyArg<B>): Option<A | B> => isNone(self) ? some(onNone()) : self
|
|
587
|
+
)
|
|
588
|
+
|
|
589
|
+
/**
|
|
590
|
+
* Similar to {@link orElse}, but returns an `Either` wrapped in an `Option` to
|
|
591
|
+
* indicate the source of the value.
|
|
592
|
+
*
|
|
593
|
+
* **Details**
|
|
594
|
+
*
|
|
595
|
+
* This function allows you to provide a fallback `Option` in case the current
|
|
596
|
+
* `Option` (`self`) is `None`. However, unlike `orElse`, it returns the value
|
|
597
|
+
* wrapped in an `Either` object, providing additional information about where
|
|
598
|
+
* the value came from:
|
|
599
|
+
*
|
|
600
|
+
* - If the value is from the fallback `Option` (`that`), it is wrapped in an
|
|
601
|
+
* `Either.right`.
|
|
602
|
+
* - If the value is from the original `Option` (`self`), it is wrapped in an
|
|
603
|
+
* `Either.left`.
|
|
604
|
+
*
|
|
605
|
+
* This is especially useful when you need to differentiate between values
|
|
606
|
+
* originating from the primary `Option` and those coming from the fallback,
|
|
607
|
+
* while still maintaining the `Option`-style handling.
|
|
608
|
+
*
|
|
609
|
+
* @category Error handling
|
|
610
|
+
* @since 2.0.0
|
|
611
|
+
*/
|
|
612
|
+
export const orElseEither: {
|
|
613
|
+
<B>(that: LazyArg<Option<B>>): <A>(self: Option<A>) => Option<Either<B, A>>
|
|
614
|
+
<A, B>(self: Option<A>, that: LazyArg<Option<B>>): Option<Either<B, A>>
|
|
615
|
+
} = dual(
|
|
616
|
+
2,
|
|
617
|
+
<A, B>(self: Option<A>, that: LazyArg<Option<B>>): Option<Either<B, A>> =>
|
|
618
|
+
isNone(self) ? map(that(), either.right) : map(self, either.left)
|
|
619
|
+
)
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* Returns the first `Some` value found in an `Iterable` collection of
|
|
623
|
+
* `Option`s, or `None` if no `Some` is found.
|
|
624
|
+
*
|
|
625
|
+
* **Details**
|
|
626
|
+
*
|
|
627
|
+
* This function iterates over a collection of `Option` values and returns the
|
|
628
|
+
* first `Some` it encounters. If the collection contains only `None` values,
|
|
629
|
+
* the result will also be `None`. This utility is useful for efficiently
|
|
630
|
+
* finding the first valid value in a sequence of potentially empty or invalid
|
|
631
|
+
* options.
|
|
632
|
+
*
|
|
633
|
+
* The iteration stops as soon as a `Some` is found, making this function
|
|
634
|
+
* efficient for large collections.
|
|
635
|
+
*
|
|
636
|
+
* @example
|
|
637
|
+
* ```ts
|
|
638
|
+
* import { Option } from "effect"
|
|
639
|
+
*
|
|
640
|
+
* console.log(Option.firstSomeOf([
|
|
641
|
+
* Option.none(),
|
|
642
|
+
* Option.some(1),
|
|
643
|
+
* Option.some(2)
|
|
644
|
+
* ]))
|
|
645
|
+
* // Output: { _id: 'Option', _tag: 'Some', value: 1 }
|
|
646
|
+
* ```
|
|
647
|
+
*
|
|
648
|
+
* @category Error handling
|
|
649
|
+
* @since 2.0.0
|
|
650
|
+
*/
|
|
651
|
+
export const firstSomeOf = <T, C extends Iterable<Option<T>> = Iterable<Option<T>>>(
|
|
652
|
+
collection: C
|
|
653
|
+
): [C] extends [Iterable<Option<infer A>>] ? Option<A> : never => {
|
|
654
|
+
let out: Option<unknown> = none()
|
|
655
|
+
for (out of collection) {
|
|
656
|
+
if (isSome(out)) {
|
|
657
|
+
return out as any
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
return out as any
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
/**
|
|
664
|
+
* Converts a nullable value into an `Option`. Returns `None` if the value is
|
|
665
|
+
* `null` or `undefined`, otherwise wraps the value in a `Some`.
|
|
666
|
+
*
|
|
667
|
+
* @example
|
|
668
|
+
* ```ts
|
|
669
|
+
* import { Option } from "effect"
|
|
670
|
+
*
|
|
671
|
+
* console.log(Option.fromNullable(undefined))
|
|
672
|
+
* // Output: { _id: 'Option', _tag: 'None' }
|
|
673
|
+
*
|
|
674
|
+
* console.log(Option.fromNullable(null))
|
|
675
|
+
* // Output: { _id: 'Option', _tag: 'None' }
|
|
676
|
+
*
|
|
677
|
+
* console.log(Option.fromNullable(1))
|
|
678
|
+
* // Output: { _id: 'Option', _tag: 'Some', value: 1 }
|
|
679
|
+
* ```
|
|
680
|
+
*
|
|
681
|
+
* @category Conversions
|
|
682
|
+
* @since 2.0.0
|
|
683
|
+
*/
|
|
684
|
+
export const fromNullable = <A>(
|
|
685
|
+
nullableValue: A
|
|
686
|
+
): Option<NonNullable<A>> => (nullableValue == null ? none() : some(nullableValue as NonNullable<A>))
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* Lifts a function that returns `null` or `undefined` into the `Option`
|
|
690
|
+
* context.
|
|
691
|
+
*
|
|
692
|
+
* **Details**
|
|
693
|
+
*
|
|
694
|
+
* This function takes a function `f` that might return `null` or `undefined`
|
|
695
|
+
* and transforms it into a function that returns an `Option`. The resulting
|
|
696
|
+
* function will return:
|
|
697
|
+
* - `Some` if the original function produces a non-null, non-undefined value.
|
|
698
|
+
* - `None` if the original function produces `null` or `undefined`.
|
|
699
|
+
*
|
|
700
|
+
* @example
|
|
701
|
+
* ```ts
|
|
702
|
+
* import { Option } from "effect"
|
|
703
|
+
*
|
|
704
|
+
* const parse = (s: string): number | undefined => {
|
|
705
|
+
* const n = parseFloat(s)
|
|
706
|
+
* return isNaN(n) ? undefined : n
|
|
707
|
+
* }
|
|
708
|
+
*
|
|
709
|
+
* const parseOption = Option.liftNullable(parse)
|
|
710
|
+
*
|
|
711
|
+
* console.log(parseOption("1"))
|
|
712
|
+
* // Output: { _id: 'Option', _tag: 'Some', value: 1 }
|
|
713
|
+
*
|
|
714
|
+
* console.log(parseOption("not a number"))
|
|
715
|
+
* // Output: { _id: 'Option', _tag: 'None' }
|
|
716
|
+
* ```
|
|
717
|
+
*
|
|
718
|
+
* @category Conversions
|
|
719
|
+
* @since 2.0.0
|
|
720
|
+
*/
|
|
721
|
+
export const liftNullable = <A extends ReadonlyArray<unknown>, B>(
|
|
722
|
+
f: (...a: A) => B | null | undefined
|
|
723
|
+
): (...a: A) => Option<NonNullable<B>> =>
|
|
724
|
+
(...a) => fromNullable(f(...a))
|
|
725
|
+
|
|
726
|
+
/**
|
|
727
|
+
* Returns the value contained in the `Option` if it is `Some`; otherwise,
|
|
728
|
+
* returns `null`.
|
|
729
|
+
*
|
|
730
|
+
* **Details**
|
|
731
|
+
*
|
|
732
|
+
* This function provides a way to extract the value of an `Option` while
|
|
733
|
+
* falling back to `null` if the `Option` is `None`.
|
|
734
|
+
*
|
|
735
|
+
* It is particularly useful in scenarios where `null` is an acceptable
|
|
736
|
+
* placeholder for the absence of a value, such as when interacting with APIs or
|
|
737
|
+
* systems that use `null` as a default for missing values.
|
|
738
|
+
*
|
|
739
|
+
* @example
|
|
740
|
+
* ```ts
|
|
741
|
+
* import { Option } from "effect"
|
|
742
|
+
*
|
|
743
|
+
* console.log(Option.getOrNull(Option.some(1)))
|
|
744
|
+
* // Output: 1
|
|
745
|
+
*
|
|
746
|
+
* console.log(Option.getOrNull(Option.none()))
|
|
747
|
+
* // Output: null
|
|
748
|
+
* ```
|
|
749
|
+
*
|
|
750
|
+
* @category Getters
|
|
751
|
+
* @since 2.0.0
|
|
752
|
+
*/
|
|
753
|
+
export const getOrNull: <A>(self: Option<A>) => A | null = getOrElse(constNull)
|
|
754
|
+
|
|
755
|
+
/**
|
|
756
|
+
* Returns the value contained in the `Option` if it is `Some`; otherwise,
|
|
757
|
+
* returns `undefined`.
|
|
758
|
+
*
|
|
759
|
+
* **Details**
|
|
760
|
+
*
|
|
761
|
+
* This function provides a way to extract the value of an `Option` while
|
|
762
|
+
* falling back to `undefined` if the `Option` is `None`.
|
|
763
|
+
*
|
|
764
|
+
* It is particularly useful in scenarios where `undefined` is an acceptable
|
|
765
|
+
* placeholder for the absence of a value, such as when interacting with APIs or
|
|
766
|
+
* systems that use `undefined` as a default for missing values.
|
|
767
|
+
*
|
|
768
|
+
* @example
|
|
769
|
+
* ```ts
|
|
770
|
+
* import { Option } from "effect"
|
|
771
|
+
*
|
|
772
|
+
* console.log(Option.getOrUndefined(Option.some(1)))
|
|
773
|
+
* // Output: 1
|
|
774
|
+
*
|
|
775
|
+
* console.log(Option.getOrUndefined(Option.none()))
|
|
776
|
+
* // Output: undefined
|
|
777
|
+
* ```
|
|
778
|
+
*
|
|
779
|
+
* @category Getters
|
|
780
|
+
* @since 2.0.0
|
|
781
|
+
*/
|
|
782
|
+
export const getOrUndefined: <A>(self: Option<A>) => A | undefined = getOrElse(constUndefined)
|
|
783
|
+
|
|
784
|
+
/**
|
|
785
|
+
* Lifts a function that throws exceptions into a function that returns an
|
|
786
|
+
* `Option`.
|
|
787
|
+
*
|
|
788
|
+
* **Details**
|
|
789
|
+
*
|
|
790
|
+
* This utility function takes a function `f` that might throw an exception and
|
|
791
|
+
* transforms it into a safer function that returns an `Option`. If the original
|
|
792
|
+
* function executes successfully, the result is wrapped in a `Some`. If an
|
|
793
|
+
* exception is thrown, the result is `None`, allowing the developer to handle
|
|
794
|
+
* errors in a functional, type-safe way.
|
|
795
|
+
*
|
|
796
|
+
* @example
|
|
797
|
+
* ```ts
|
|
798
|
+
* import { Option } from "effect"
|
|
799
|
+
*
|
|
800
|
+
* const parse = Option.liftThrowable(JSON.parse)
|
|
801
|
+
*
|
|
802
|
+
* console.log(parse("1"))
|
|
803
|
+
* // Output: { _id: 'Option', _tag: 'Some', value: 1 }
|
|
804
|
+
*
|
|
805
|
+
* console.log(parse(""))
|
|
806
|
+
* // Output: { _id: 'Option', _tag: 'None' }
|
|
807
|
+
* ```
|
|
808
|
+
*
|
|
809
|
+
* @category Conversions
|
|
810
|
+
* @since 2.0.0
|
|
811
|
+
*/
|
|
812
|
+
export const liftThrowable = <A extends ReadonlyArray<unknown>, B>(
|
|
813
|
+
f: (...a: A) => B
|
|
814
|
+
): (...a: A) => Option<B> =>
|
|
815
|
+
(...a) => {
|
|
816
|
+
try {
|
|
817
|
+
return some(f(...a))
|
|
818
|
+
} catch {
|
|
819
|
+
return none()
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* Extracts the value of an `Option` or throws an error if the `Option` is
|
|
825
|
+
* `None`, using a custom error factory.
|
|
826
|
+
*
|
|
827
|
+
* **Details**
|
|
828
|
+
*
|
|
829
|
+
* This function allows you to extract the value of an `Option` when it is
|
|
830
|
+
* `Some`. If the `Option` is `None`, it throws an error generated by the
|
|
831
|
+
* provided `onNone` function. This utility is particularly useful when you need
|
|
832
|
+
* a fail-fast behavior for empty `Option` values and want to provide a custom
|
|
833
|
+
* error message or object.
|
|
834
|
+
*
|
|
835
|
+
* @example
|
|
836
|
+
* ```ts
|
|
837
|
+
* import * as assert from "node:assert"
|
|
838
|
+
* import { Option } from "effect"
|
|
839
|
+
*
|
|
840
|
+
* assert.deepStrictEqual(
|
|
841
|
+
* Option.getOrThrowWith(Option.some(1), () => new Error('Unexpected None')),
|
|
842
|
+
* 1
|
|
843
|
+
* )
|
|
844
|
+
* assert.throws(() => Option.getOrThrowWith(Option.none(), () => new Error('Unexpected None')))
|
|
845
|
+
* ```
|
|
846
|
+
*
|
|
847
|
+
* @see {@link getOrThrow} for a version that throws a default error.
|
|
848
|
+
*
|
|
849
|
+
* @category Conversions
|
|
850
|
+
* @since 2.0.0
|
|
851
|
+
*/
|
|
852
|
+
export const getOrThrowWith: {
|
|
853
|
+
(onNone: () => unknown): <A>(self: Option<A>) => A
|
|
854
|
+
<A>(self: Option<A>, onNone: () => unknown): A
|
|
855
|
+
} = dual(2, <A>(self: Option<A>, onNone: () => unknown): A => {
|
|
856
|
+
if (isSome(self)) {
|
|
857
|
+
return self.value
|
|
858
|
+
}
|
|
859
|
+
throw onNone()
|
|
860
|
+
})
|
|
861
|
+
|
|
862
|
+
/**
|
|
863
|
+
* Extracts the value of an `Option` or throws a default error if the `Option`
|
|
864
|
+
* is `None`.
|
|
865
|
+
*
|
|
866
|
+
* **Details**
|
|
867
|
+
*
|
|
868
|
+
* This function extracts the value from an `Option` if it is `Some`. If the
|
|
869
|
+
* `Option` is `None`, it throws a default error. It is useful for fail-fast
|
|
870
|
+
* scenarios where the absence of a value is treated as an exceptional case and
|
|
871
|
+
* a default error is sufficient.
|
|
872
|
+
*
|
|
873
|
+
* @example
|
|
874
|
+
* ```ts
|
|
875
|
+
* import * as assert from "node:assert"
|
|
876
|
+
* import { Option } from "effect"
|
|
877
|
+
*
|
|
878
|
+
* assert.deepStrictEqual(Option.getOrThrow(Option.some(1)), 1)
|
|
879
|
+
* assert.throws(() => Option.getOrThrow(Option.none()))
|
|
880
|
+
* ```
|
|
881
|
+
*
|
|
882
|
+
* @see {@link getOrThrowWith} for a version that allows you to provide a custom error.
|
|
883
|
+
*
|
|
884
|
+
* @category Conversions
|
|
885
|
+
* @since 2.0.0
|
|
886
|
+
*/
|
|
887
|
+
export const getOrThrow: <A>(self: Option<A>) => A = getOrThrowWith(() => new Error("getOrThrow called on a None"))
|
|
888
|
+
|
|
889
|
+
/**
|
|
890
|
+
* Transforms the value inside a `Some` to a new value using the provided
|
|
891
|
+
* function, while leaving `None` unchanged.
|
|
892
|
+
*
|
|
893
|
+
* **Details**
|
|
894
|
+
*
|
|
895
|
+
* This function applies a mapping function `f` to the value inside an `Option`
|
|
896
|
+
* if it is a `Some`. If the `Option` is `None`, it remains unchanged. The
|
|
897
|
+
* result is a new `Option` with the transformed value (if it was a `Some`) or
|
|
898
|
+
* still `None`.
|
|
899
|
+
*
|
|
900
|
+
* This utility is particularly useful for chaining transformations in a
|
|
901
|
+
* functional way without needing to manually handle `None` cases.
|
|
902
|
+
*
|
|
903
|
+
* @example
|
|
904
|
+
* ```ts
|
|
905
|
+
* import { Option } from "effect"
|
|
906
|
+
*
|
|
907
|
+
* // Mapping over a `Some`
|
|
908
|
+
* const someValue = Option.some(2)
|
|
909
|
+
*
|
|
910
|
+
* console.log(Option.map(someValue, (n) => n * 2))
|
|
911
|
+
* // Output: { _id: 'Option', _tag: 'Some', value: 4 }
|
|
912
|
+
*
|
|
913
|
+
* // Mapping over a `None`
|
|
914
|
+
* const noneValue = Option.none<number>()
|
|
915
|
+
*
|
|
916
|
+
* console.log(Option.map(noneValue, (n) => n * 2))
|
|
917
|
+
* // Output: { _id: 'Option', _tag: 'None' }
|
|
918
|
+
* ```
|
|
919
|
+
*
|
|
920
|
+
* @category Mapping
|
|
921
|
+
* @since 2.0.0
|
|
922
|
+
*/
|
|
923
|
+
export const map: {
|
|
924
|
+
<A, B>(f: (a: A) => B): (self: Option<A>) => Option<B>
|
|
925
|
+
<A, B>(self: Option<A>, f: (a: A) => B): Option<B>
|
|
926
|
+
} = dual(
|
|
927
|
+
2,
|
|
928
|
+
<A, B>(self: Option<A>, f: (a: A) => B): Option<B> => isNone(self) ? none() : some(f(self.value))
|
|
929
|
+
)
|
|
930
|
+
|
|
931
|
+
/**
|
|
932
|
+
* Replaces the value inside a `Some` with the specified constant value, leaving
|
|
933
|
+
* `None` unchanged.
|
|
934
|
+
*
|
|
935
|
+
* **Details**
|
|
936
|
+
*
|
|
937
|
+
* This function transforms an `Option` by replacing the value inside a `Some`
|
|
938
|
+
* with the given constant value `b`. If the `Option` is `None`, it remains
|
|
939
|
+
* unchanged.
|
|
940
|
+
*
|
|
941
|
+
* This is useful when you want to preserve the presence of a value (`Some`) but
|
|
942
|
+
* replace its content with a fixed value.
|
|
943
|
+
*
|
|
944
|
+
* @example
|
|
945
|
+
* ```ts
|
|
946
|
+
* import { Option } from "effect"
|
|
947
|
+
*
|
|
948
|
+
* // Replacing the value of a `Some`
|
|
949
|
+
* const someValue = Option.some(42)
|
|
950
|
+
*
|
|
951
|
+
* console.log(Option.as(someValue, "new value"))
|
|
952
|
+
* // Output: { _id: 'Option', _tag: 'Some', value: 'new value' }
|
|
953
|
+
*
|
|
954
|
+
* // Replacing a `None` (no effect)
|
|
955
|
+
* const noneValue = Option.none<number>()
|
|
956
|
+
*
|
|
957
|
+
* console.log(Option.as(noneValue, "new value"))
|
|
958
|
+
* // Output: { _id: 'Option', _tag: 'None' }
|
|
959
|
+
* ```
|
|
960
|
+
*
|
|
961
|
+
* @category Mapping
|
|
962
|
+
* @since 2.0.0
|
|
963
|
+
*/
|
|
964
|
+
export const as: {
|
|
965
|
+
<B>(b: B): <X>(self: Option<X>) => Option<B>
|
|
966
|
+
<X, B>(self: Option<X>, b: B): Option<B>
|
|
967
|
+
} = dual(2, <X, B>(self: Option<X>, b: B): Option<B> => map(self, () => b))
|
|
968
|
+
|
|
969
|
+
/**
|
|
970
|
+
* Replaces the value inside a `Some` with the constant value `void`, leaving
|
|
971
|
+
* `None` unchanged.
|
|
972
|
+
*
|
|
973
|
+
* **Details**
|
|
974
|
+
*
|
|
975
|
+
* This function transforms an `Option` by replacing the value inside a `Some`
|
|
976
|
+
* with `void`. If the `Option` is `None`, it remains unchanged.
|
|
977
|
+
*
|
|
978
|
+
* This is particularly useful in scenarios where the presence or absence of a
|
|
979
|
+
* value is significant, but the actual content of the value is irrelevant.
|
|
980
|
+
*
|
|
981
|
+
* @category Mapping
|
|
982
|
+
* @since 2.0.0
|
|
983
|
+
*/
|
|
984
|
+
export const asVoid: <_>(self: Option<_>) => Option<void> = as(undefined)
|
|
985
|
+
|
|
986
|
+
const void_: Option<void> = some(undefined)
|
|
987
|
+
export {
|
|
988
|
+
/**
|
|
989
|
+
* @since 2.0.0
|
|
990
|
+
*/
|
|
991
|
+
void_ as void
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
/**
|
|
995
|
+
* Applies a function to the value of a `Some` and flattens the resulting
|
|
996
|
+
* `Option`. If the input is `None`, it remains `None`.
|
|
997
|
+
*
|
|
998
|
+
* **Details**
|
|
999
|
+
*
|
|
1000
|
+
* This function allows you to chain computations that return `Option` values.
|
|
1001
|
+
* If the input `Option` is `Some`, the provided function `f` is applied to the
|
|
1002
|
+
* contained value, and the resulting `Option` is returned. If the input is
|
|
1003
|
+
* `None`, the function is not applied, and the result remains `None`.
|
|
1004
|
+
*
|
|
1005
|
+
* This utility is particularly useful for sequencing operations that may fail
|
|
1006
|
+
* or produce optional results, enabling clean and concise workflows for
|
|
1007
|
+
* handling such cases.
|
|
1008
|
+
*
|
|
1009
|
+
* @example
|
|
1010
|
+
* ```ts
|
|
1011
|
+
* import { Option } from "effect"
|
|
1012
|
+
*
|
|
1013
|
+
* interface Address {
|
|
1014
|
+
* readonly city: string
|
|
1015
|
+
* readonly street: Option.Option<string>
|
|
1016
|
+
* }
|
|
1017
|
+
*
|
|
1018
|
+
* interface User {
|
|
1019
|
+
* readonly id: number
|
|
1020
|
+
* readonly username: string
|
|
1021
|
+
* readonly email: Option.Option<string>
|
|
1022
|
+
* readonly address: Option.Option<Address>
|
|
1023
|
+
* }
|
|
1024
|
+
*
|
|
1025
|
+
* const user: User = {
|
|
1026
|
+
* id: 1,
|
|
1027
|
+
* username: "john_doe",
|
|
1028
|
+
* email: Option.some("john.doe@example.com"),
|
|
1029
|
+
* address: Option.some({
|
|
1030
|
+
* city: "New York",
|
|
1031
|
+
* street: Option.some("123 Main St")
|
|
1032
|
+
* })
|
|
1033
|
+
* }
|
|
1034
|
+
*
|
|
1035
|
+
* // Use flatMap to extract the street value
|
|
1036
|
+
* const street = user.address.pipe(
|
|
1037
|
+
* Option.flatMap((address) => address.street)
|
|
1038
|
+
* )
|
|
1039
|
+
*
|
|
1040
|
+
* console.log(street)
|
|
1041
|
+
* // Output: { _id: 'Option', _tag: 'Some', value: '123 Main St' }
|
|
1042
|
+
* ```
|
|
1043
|
+
*
|
|
1044
|
+
* @category Sequencing
|
|
1045
|
+
* @since 2.0.0
|
|
1046
|
+
*/
|
|
1047
|
+
export const flatMap: {
|
|
1048
|
+
<A, B>(f: (a: A) => Option<B>): (self: Option<A>) => Option<B>
|
|
1049
|
+
<A, B>(self: Option<A>, f: (a: A) => Option<B>): Option<B>
|
|
1050
|
+
} = dual(
|
|
1051
|
+
2,
|
|
1052
|
+
<A, B>(self: Option<A>, f: (a: A) => Option<B>): Option<B> => isNone(self) ? none() : f(self.value)
|
|
1053
|
+
)
|
|
1054
|
+
|
|
1055
|
+
/**
|
|
1056
|
+
* Chains two `Option`s together. The second `Option` can either be a static
|
|
1057
|
+
* value or depend on the result of the first `Option`.
|
|
1058
|
+
*
|
|
1059
|
+
* **Details**
|
|
1060
|
+
*
|
|
1061
|
+
* This function enables sequencing of two `Option` computations. If the first
|
|
1062
|
+
* `Option` is `Some`, the second `Option` is evaluated. The second `Option` can
|
|
1063
|
+
* either:
|
|
1064
|
+
*
|
|
1065
|
+
* - Be a static `Option` value.
|
|
1066
|
+
* - Be a function that produces an `Option`, optionally based on the value of
|
|
1067
|
+
* the first `Option`.
|
|
1068
|
+
*
|
|
1069
|
+
* If the first `Option` is `None`, the function skips the evaluation of the
|
|
1070
|
+
* second `Option` and directly returns `None`.
|
|
1071
|
+
*
|
|
1072
|
+
* @category Sequencing
|
|
1073
|
+
* @since 2.0.0
|
|
1074
|
+
*/
|
|
1075
|
+
export const andThen: {
|
|
1076
|
+
<A, B>(f: (a: A) => Option<B>): (self: Option<A>) => Option<B>
|
|
1077
|
+
<B>(f: Option<B>): <A>(self: Option<A>) => Option<B>
|
|
1078
|
+
<A, B>(f: (a: A) => B): (self: Option<A>) => Option<B>
|
|
1079
|
+
<B>(f: NotFunction<B>): <A>(self: Option<A>) => Option<B>
|
|
1080
|
+
<A, B>(self: Option<A>, f: (a: A) => Option<B>): Option<B>
|
|
1081
|
+
<A, B>(self: Option<A>, f: Option<B>): Option<B>
|
|
1082
|
+
<A, B>(self: Option<A>, f: (a: A) => B): Option<B>
|
|
1083
|
+
<A, B>(self: Option<A>, f: NotFunction<B>): Option<B>
|
|
1084
|
+
} = dual(
|
|
1085
|
+
2,
|
|
1086
|
+
<A, B>(self: Option<A>, f: (a: A) => Option<B> | Option<B>): Option<B> =>
|
|
1087
|
+
flatMap(self, (a) => {
|
|
1088
|
+
const b = isFunction(f) ? f(a) : f
|
|
1089
|
+
return isOption(b) ? b : some(b)
|
|
1090
|
+
})
|
|
1091
|
+
)
|
|
1092
|
+
|
|
1093
|
+
/**
|
|
1094
|
+
* Combines `flatMap` and `fromNullable`, transforming the value inside a `Some`
|
|
1095
|
+
* using a function that may return `null` or `undefined`.
|
|
1096
|
+
*
|
|
1097
|
+
* **Details**
|
|
1098
|
+
*
|
|
1099
|
+
* This function applies a transformation function `f` to the value inside a
|
|
1100
|
+
* `Some`. The function `f` may return a value, `null`, or `undefined`. If `f`
|
|
1101
|
+
* returns a value, it is wrapped in a `Some`. If `f` returns `null` or
|
|
1102
|
+
* `undefined`, the result is `None`. If the input `Option` is `None`, the
|
|
1103
|
+
* function is not applied, and `None` is returned.
|
|
1104
|
+
*
|
|
1105
|
+
* This utility is particularly useful when working with deeply nested optional
|
|
1106
|
+
* values or chaining computations that may result in `null` or `undefined` at
|
|
1107
|
+
* some point.
|
|
1108
|
+
*
|
|
1109
|
+
* @example
|
|
1110
|
+
* ```ts
|
|
1111
|
+
* import { Option } from "effect"
|
|
1112
|
+
*
|
|
1113
|
+
* interface Employee {
|
|
1114
|
+
* company?: {
|
|
1115
|
+
* address?: {
|
|
1116
|
+
* street?: {
|
|
1117
|
+
* name?: string
|
|
1118
|
+
* }
|
|
1119
|
+
* }
|
|
1120
|
+
* }
|
|
1121
|
+
* }
|
|
1122
|
+
*
|
|
1123
|
+
* const employee1: Employee = { company: { address: { street: { name: "high street" } } } }
|
|
1124
|
+
*
|
|
1125
|
+
* // Extracting a deeply nested property
|
|
1126
|
+
* console.log(
|
|
1127
|
+
* Option.some(employee1)
|
|
1128
|
+
* .pipe(Option.flatMapNullable((employee) => employee.company?.address?.street?.name))
|
|
1129
|
+
* )
|
|
1130
|
+
* // Output: { _id: 'Option', _tag: 'Some', value: 'high street' }
|
|
1131
|
+
*
|
|
1132
|
+
* const employee2: Employee = { company: { address: { street: {} } } }
|
|
1133
|
+
*
|
|
1134
|
+
* // Property does not exist
|
|
1135
|
+
* console.log(
|
|
1136
|
+
* Option.some(employee2)
|
|
1137
|
+
* .pipe(Option.flatMapNullable((employee) => employee.company?.address?.street?.name))
|
|
1138
|
+
* )
|
|
1139
|
+
* // Output: { _id: 'Option', _tag: 'None' }
|
|
1140
|
+
* ```
|
|
1141
|
+
*
|
|
1142
|
+
* @category Sequencing
|
|
1143
|
+
* @since 2.0.0
|
|
1144
|
+
*/
|
|
1145
|
+
export const flatMapNullable: {
|
|
1146
|
+
<A, B>(f: (a: A) => B | null | undefined): (self: Option<A>) => Option<NonNullable<B>>
|
|
1147
|
+
<A, B>(self: Option<A>, f: (a: A) => B | null | undefined): Option<NonNullable<B>>
|
|
1148
|
+
} = dual(
|
|
1149
|
+
2,
|
|
1150
|
+
<A, B>(self: Option<A>, f: (a: A) => B | null | undefined): Option<NonNullable<B>> =>
|
|
1151
|
+
isNone(self) ? none() : fromNullable(f(self.value))
|
|
1152
|
+
)
|
|
1153
|
+
|
|
1154
|
+
/**
|
|
1155
|
+
* Flattens an `Option` of `Option` into a single `Option`.
|
|
1156
|
+
*
|
|
1157
|
+
* **Details**
|
|
1158
|
+
*
|
|
1159
|
+
* This function takes an `Option` that wraps another `Option` and flattens it
|
|
1160
|
+
* into a single `Option`. If the outer `Option` is `Some`, the function
|
|
1161
|
+
* extracts the inner `Option`. If the outer `Option` is `None`, the result
|
|
1162
|
+
* remains `None`.
|
|
1163
|
+
*
|
|
1164
|
+
* This is useful for simplifying nested `Option` structures that may arise
|
|
1165
|
+
* during functional operations.
|
|
1166
|
+
*
|
|
1167
|
+
* @category Sequencing
|
|
1168
|
+
* @since 2.0.0
|
|
1169
|
+
*/
|
|
1170
|
+
export const flatten: <A>(self: Option<Option<A>>) => Option<A> = flatMap(identity)
|
|
1171
|
+
|
|
1172
|
+
/**
|
|
1173
|
+
* Combines two `Option`s, keeping the value from the second `Option` if both
|
|
1174
|
+
* are `Some`.
|
|
1175
|
+
*
|
|
1176
|
+
* **Details**
|
|
1177
|
+
*
|
|
1178
|
+
* This function takes two `Option`s and returns the second one if the first is
|
|
1179
|
+
* `Some`. If the first `Option` is `None`, the result will also be `None`,
|
|
1180
|
+
* regardless of the second `Option`. It effectively "zips" the two `Option`s
|
|
1181
|
+
* while discarding the value from the first `Option`.
|
|
1182
|
+
*
|
|
1183
|
+
* This is particularly useful when sequencing computations where the result of
|
|
1184
|
+
* the first computation is not needed, and you only care about the result of
|
|
1185
|
+
* the second computation.
|
|
1186
|
+
*
|
|
1187
|
+
* @category Zipping
|
|
1188
|
+
* @since 2.0.0
|
|
1189
|
+
*/
|
|
1190
|
+
export const zipRight: {
|
|
1191
|
+
<B>(that: Option<B>): <_>(self: Option<_>) => Option<B>
|
|
1192
|
+
<X, B>(self: Option<X>, that: Option<B>): Option<B>
|
|
1193
|
+
} = dual(2, <X, B>(self: Option<X>, that: Option<B>): Option<B> => flatMap(self, () => that))
|
|
1194
|
+
|
|
1195
|
+
/**
|
|
1196
|
+
* Combines two `Option`s, keeping the value from the first `Option` if both are
|
|
1197
|
+
* `Some`.
|
|
1198
|
+
*
|
|
1199
|
+
* **Details**
|
|
1200
|
+
*
|
|
1201
|
+
* This function takes two `Option`s and returns the first one if it is `Some`.
|
|
1202
|
+
* If either the first `Option` or the second `Option` is `None`, the result
|
|
1203
|
+
* will be `None`. This operation "zips" the two `Option`s while discarding the
|
|
1204
|
+
* value from the second `Option`.
|
|
1205
|
+
*
|
|
1206
|
+
* This is useful when sequencing computations where the second `Option`
|
|
1207
|
+
* represents a dependency or condition that must hold, but its value is
|
|
1208
|
+
* irrelevant.
|
|
1209
|
+
*
|
|
1210
|
+
* @category Zipping
|
|
1211
|
+
* @since 2.0.0
|
|
1212
|
+
*/
|
|
1213
|
+
export const zipLeft: {
|
|
1214
|
+
<_>(that: Option<_>): <A>(self: Option<A>) => Option<A>
|
|
1215
|
+
<A, X>(self: Option<A>, that: Option<X>): Option<A>
|
|
1216
|
+
} = dual(2, <A, X>(self: Option<A>, that: Option<X>): Option<A> => tap(self, () => that))
|
|
1217
|
+
|
|
1218
|
+
/**
|
|
1219
|
+
* Composes two functions that return `Option` values, creating a new function
|
|
1220
|
+
* that chains them together.
|
|
1221
|
+
*
|
|
1222
|
+
* **Details**
|
|
1223
|
+
*
|
|
1224
|
+
* This function allows you to compose two computations, each represented by a
|
|
1225
|
+
* function that returns an `Option`. The result of the first function is passed
|
|
1226
|
+
* to the second function if it is `Some`. If the first function returns `None`,
|
|
1227
|
+
* the composed function short-circuits and returns `None` without invoking the
|
|
1228
|
+
* second function.
|
|
1229
|
+
*
|
|
1230
|
+
* @example
|
|
1231
|
+
* ```ts
|
|
1232
|
+
* import { Option } from "effect"
|
|
1233
|
+
*
|
|
1234
|
+
* const parse = (s: string): Option.Option<number> => isNaN(Number(s)) ? Option.none() : Option.some(Number(s))
|
|
1235
|
+
*
|
|
1236
|
+
* const double = (n: number): Option.Option<number> => n > 0 ? Option.some(n * 2) : Option.none()
|
|
1237
|
+
*
|
|
1238
|
+
* const parseAndDouble = Option.composeK(parse, double)
|
|
1239
|
+
*
|
|
1240
|
+
* console.log(parseAndDouble("42"))
|
|
1241
|
+
* // Output: { _id: 'Option', _tag: 'Some', value: 84 }
|
|
1242
|
+
*
|
|
1243
|
+
* console.log(parseAndDouble("not a number"))
|
|
1244
|
+
* // Output: { _id: 'Option', _tag: 'None' }
|
|
1245
|
+
* ```
|
|
1246
|
+
*
|
|
1247
|
+
* @category Sequencing
|
|
1248
|
+
* @since 2.0.0
|
|
1249
|
+
*/
|
|
1250
|
+
export const composeK: {
|
|
1251
|
+
<B, C>(bfc: (b: B) => Option<C>): <A>(afb: (a: A) => Option<B>) => (a: A) => Option<C>
|
|
1252
|
+
<A, B, C>(afb: (a: A) => Option<B>, bfc: (b: B) => Option<C>): (a: A) => Option<C>
|
|
1253
|
+
} = dual(2, <A, B, C>(afb: (a: A) => Option<B>, bfc: (b: B) => Option<C>) => (a: A): Option<C> => flatMap(afb(a), bfc))
|
|
1254
|
+
|
|
1255
|
+
/**
|
|
1256
|
+
* Applies the provided function `f` to the value of the `Option` if it is
|
|
1257
|
+
* `Some` and returns the original `Option`, unless `f` returns `None`, in which
|
|
1258
|
+
* case it returns `None`.
|
|
1259
|
+
*
|
|
1260
|
+
* **Details**
|
|
1261
|
+
*
|
|
1262
|
+
* This function allows you to perform additional computations on the value of
|
|
1263
|
+
* an `Option` without modifying its original value. If the `Option` is `Some`,
|
|
1264
|
+
* the provided function `f` is executed with the value, and its result
|
|
1265
|
+
* determines whether the original `Option` is returned (`Some`) or the result
|
|
1266
|
+
* is `None` if `f` returns `None`. If the input `Option` is `None`, the
|
|
1267
|
+
* function is not executed, and `None` is returned.
|
|
1268
|
+
*
|
|
1269
|
+
* This is particularly useful for applying side conditions or performing
|
|
1270
|
+
* validation checks while retaining the original `Option`'s value.
|
|
1271
|
+
*
|
|
1272
|
+
* @example
|
|
1273
|
+
* ```ts
|
|
1274
|
+
* import { Option } from "effect"
|
|
1275
|
+
*
|
|
1276
|
+
* const getInteger = (n: number) => Number.isInteger(n) ? Option.some(n) : Option.none()
|
|
1277
|
+
*
|
|
1278
|
+
* console.log(Option.tap(Option.none(), getInteger))
|
|
1279
|
+
* // Output: { _id: 'Option', _tag: 'None' }
|
|
1280
|
+
*
|
|
1281
|
+
* console.log(Option.tap(Option.some(1), getInteger))
|
|
1282
|
+
* // Output: { _id: 'Option', _tag: 'Some', value: 1 }
|
|
1283
|
+
*
|
|
1284
|
+
* console.log(Option.tap(Option.some(1.14), getInteger))
|
|
1285
|
+
* // Output: { _id: 'Option', _tag: 'None' }
|
|
1286
|
+
* ```
|
|
1287
|
+
*
|
|
1288
|
+
* @category Sequencing
|
|
1289
|
+
* @since 2.0.0
|
|
1290
|
+
*/
|
|
1291
|
+
export const tap: {
|
|
1292
|
+
<A, X>(f: (a: A) => Option<X>): (self: Option<A>) => Option<A>
|
|
1293
|
+
<A, X>(self: Option<A>, f: (a: A) => Option<X>): Option<A>
|
|
1294
|
+
} = dual(2, <A, X>(self: Option<A>, f: (a: A) => Option<X>): Option<A> => flatMap(self, (a) => map(f(a), () => a)))
|
|
1295
|
+
|
|
1296
|
+
/**
|
|
1297
|
+
* Combines two `Option` values into a single `Option` containing a tuple of
|
|
1298
|
+
* their values if both are `Some`.
|
|
1299
|
+
*
|
|
1300
|
+
* **Details**
|
|
1301
|
+
*
|
|
1302
|
+
* This function takes two `Option`s and combines their values into a tuple `[A,
|
|
1303
|
+
* B]` if both are `Some`. If either of the `Option`s is `None`, the result is
|
|
1304
|
+
* `None`. This is particularly useful for combining multiple `Option` values
|
|
1305
|
+
* into a single one, ensuring both contain valid values.
|
|
1306
|
+
*
|
|
1307
|
+
* @category Combining
|
|
1308
|
+
* @since 2.0.0
|
|
1309
|
+
*/
|
|
1310
|
+
export const product = <A, B>(self: Option<A>, that: Option<B>): Option<[A, B]> =>
|
|
1311
|
+
isSome(self) && isSome(that) ? some([self.value, that.value]) : none()
|
|
1312
|
+
|
|
1313
|
+
/**
|
|
1314
|
+
* Combines an `Option` with a collection of `Option`s into a single `Option`
|
|
1315
|
+
* containing a tuple of their values if all are `Some`.
|
|
1316
|
+
*
|
|
1317
|
+
* **Details**
|
|
1318
|
+
*
|
|
1319
|
+
* This function takes a primary `Option` and a collection of `Option`s and
|
|
1320
|
+
* combines their values into a tuple `[A, ...Array<A>]` if all are `Some`. If
|
|
1321
|
+
* the primary `Option` or any `Option` in the collection is `None`, the result
|
|
1322
|
+
* is `None`.
|
|
1323
|
+
*
|
|
1324
|
+
* @category Combining
|
|
1325
|
+
* @since 2.0.0
|
|
1326
|
+
*/
|
|
1327
|
+
export const productMany = <A>(
|
|
1328
|
+
self: Option<A>,
|
|
1329
|
+
collection: Iterable<Option<A>>
|
|
1330
|
+
): Option<[A, ...Array<A>]> => {
|
|
1331
|
+
if (isNone(self)) {
|
|
1332
|
+
return none()
|
|
1333
|
+
}
|
|
1334
|
+
const out: [A, ...Array<A>] = [self.value]
|
|
1335
|
+
for (const o of collection) {
|
|
1336
|
+
if (isNone(o)) {
|
|
1337
|
+
return none()
|
|
1338
|
+
}
|
|
1339
|
+
out.push(o.value)
|
|
1340
|
+
}
|
|
1341
|
+
return some(out)
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
/**
|
|
1345
|
+
* Combines a structure of `Option`s into a single `Option` containing the
|
|
1346
|
+
* values with the same structure.
|
|
1347
|
+
*
|
|
1348
|
+
* **Details**
|
|
1349
|
+
*
|
|
1350
|
+
* This function takes a structure of `Option`s (a tuple, struct, or iterable)
|
|
1351
|
+
* and produces a single `Option` that contains the values from the input
|
|
1352
|
+
* structure if all `Option`s are `Some`. If any `Option` in the input is
|
|
1353
|
+
* `None`, the result is `None`. The structure of the input is preserved in the
|
|
1354
|
+
* output.
|
|
1355
|
+
*
|
|
1356
|
+
* - If the input is a tuple (e.g., an array), the result will be an `Option`
|
|
1357
|
+
* containing a tuple with the same length.
|
|
1358
|
+
* - If the input is a struct (e.g., an object), the result will be an `Option`
|
|
1359
|
+
* containing a struct with the same keys.
|
|
1360
|
+
* - If the input is an iterable, the result will be an `Option` containing an
|
|
1361
|
+
* array.
|
|
1362
|
+
*
|
|
1363
|
+
* @example
|
|
1364
|
+
* ```ts
|
|
1365
|
+
* import { Option } from "effect"
|
|
1366
|
+
*
|
|
1367
|
+
* const maybeName: Option.Option<string> = Option.some("John")
|
|
1368
|
+
* const maybeAge: Option.Option<number> = Option.some(25)
|
|
1369
|
+
*
|
|
1370
|
+
* // ┌─── Option<[string, number]>
|
|
1371
|
+
* // ▼
|
|
1372
|
+
* const tuple = Option.all([maybeName, maybeAge])
|
|
1373
|
+
* console.log(tuple)
|
|
1374
|
+
* // Output:
|
|
1375
|
+
* // { _id: 'Option', _tag: 'Some', value: [ 'John', 25 ] }
|
|
1376
|
+
*
|
|
1377
|
+
* // ┌─── Option<{ name: string; age: number; }>
|
|
1378
|
+
* // ▼
|
|
1379
|
+
* const struct = Option.all({ name: maybeName, age: maybeAge })
|
|
1380
|
+
* console.log(struct)
|
|
1381
|
+
* // Output:
|
|
1382
|
+
* // { _id: 'Option', _tag: 'Some', value: { name: 'John', age: 25 } }
|
|
1383
|
+
* ```
|
|
1384
|
+
*
|
|
1385
|
+
* @category Combining
|
|
1386
|
+
* @since 2.0.0
|
|
1387
|
+
*/
|
|
1388
|
+
// @ts-expect-error
|
|
1389
|
+
export const all: <const I extends Iterable<Option<any>> | Record<string, Option<any>>>(
|
|
1390
|
+
input: I
|
|
1391
|
+
) => [I] extends [ReadonlyArray<Option<any>>] ? Option<
|
|
1392
|
+
{ -readonly [K in keyof I]: [I[K]] extends [Option<infer A>] ? A : never }
|
|
1393
|
+
>
|
|
1394
|
+
: [I] extends [Iterable<Option<infer A>>] ? Option<Array<A>>
|
|
1395
|
+
: Option<{ -readonly [K in keyof I]: [I[K]] extends [Option<infer A>] ? A : never }> = (
|
|
1396
|
+
input: Iterable<Option<any>> | Record<string, Option<any>>
|
|
1397
|
+
): Option<any> => {
|
|
1398
|
+
if (Symbol.iterator in input) {
|
|
1399
|
+
const out: Array<Option<any>> = []
|
|
1400
|
+
for (const o of (input as Iterable<Option<any>>)) {
|
|
1401
|
+
if (isNone(o)) {
|
|
1402
|
+
return none()
|
|
1403
|
+
}
|
|
1404
|
+
out.push(o.value)
|
|
1405
|
+
}
|
|
1406
|
+
return some(out)
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
const out: Record<string, any> = {}
|
|
1410
|
+
for (const key of Object.keys(input)) {
|
|
1411
|
+
const o = input[key]
|
|
1412
|
+
if (isNone(o)) {
|
|
1413
|
+
return none()
|
|
1414
|
+
}
|
|
1415
|
+
out[key] = o.value
|
|
1416
|
+
}
|
|
1417
|
+
return some(out)
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
/**
|
|
1421
|
+
* Combines two `Option` values into a new `Option` by applying a provided
|
|
1422
|
+
* function to their values.
|
|
1423
|
+
*
|
|
1424
|
+
* **Details**
|
|
1425
|
+
*
|
|
1426
|
+
* This function takes two `Option` values (`self` and `that`) and a combining
|
|
1427
|
+
* function `f`. If both `Option` values are `Some`, the function `f` is applied
|
|
1428
|
+
* to their values, and the result is wrapped in a new `Some`. If either
|
|
1429
|
+
* `Option` is `None`, the result is `None`.
|
|
1430
|
+
*
|
|
1431
|
+
* This utility is useful for combining two optional computations into a single
|
|
1432
|
+
* result while maintaining type safety and avoiding explicit checks for `None`.
|
|
1433
|
+
*
|
|
1434
|
+
* @example
|
|
1435
|
+
* ```ts
|
|
1436
|
+
* import { Option } from "effect"
|
|
1437
|
+
*
|
|
1438
|
+
* const maybeName: Option.Option<string> = Option.some("John")
|
|
1439
|
+
* const maybeAge: Option.Option<number> = Option.some(25)
|
|
1440
|
+
*
|
|
1441
|
+
* // Combine the name and age into a person object
|
|
1442
|
+
* const person = Option.zipWith(maybeName, maybeAge, (name, age) => ({
|
|
1443
|
+
* name: name.toUpperCase(),
|
|
1444
|
+
* age
|
|
1445
|
+
* }))
|
|
1446
|
+
*
|
|
1447
|
+
* console.log(person)
|
|
1448
|
+
* // Output:
|
|
1449
|
+
* // { _id: 'Option', _tag: 'Some', value: { name: 'JOHN', age: 25 } }
|
|
1450
|
+
* ```
|
|
1451
|
+
*
|
|
1452
|
+
* @category Zipping
|
|
1453
|
+
* @since 2.0.0
|
|
1454
|
+
*/
|
|
1455
|
+
export const zipWith: {
|
|
1456
|
+
<B, A, C>(that: Option<B>, f: (a: A, b: B) => C): (self: Option<A>) => Option<C>
|
|
1457
|
+
<A, B, C>(self: Option<A>, that: Option<B>, f: (a: A, b: B) => C): Option<C>
|
|
1458
|
+
} = dual(
|
|
1459
|
+
3,
|
|
1460
|
+
<A, B, C>(self: Option<A>, that: Option<B>, f: (a: A, b: B) => C): Option<C> =>
|
|
1461
|
+
map(product(self, that), ([a, b]) => f(a, b))
|
|
1462
|
+
)
|
|
1463
|
+
|
|
1464
|
+
/**
|
|
1465
|
+
* Applies a function inside a `Some` to a value inside another `Some`,
|
|
1466
|
+
* combining them into a new `Option`.
|
|
1467
|
+
*
|
|
1468
|
+
* **Details**
|
|
1469
|
+
*
|
|
1470
|
+
* This function allows you to apply a function wrapped in an `Option` (`self`)
|
|
1471
|
+
* to a value wrapped in another `Option` (`that`). If both `Option`s are
|
|
1472
|
+
* `Some`, the function is applied to the value, and the result is wrapped in a
|
|
1473
|
+
* new `Some`. If either `Option` is `None`, the result is `None`.
|
|
1474
|
+
*
|
|
1475
|
+
* @category Combining
|
|
1476
|
+
* @since 2.0.0
|
|
1477
|
+
*/
|
|
1478
|
+
export const ap: {
|
|
1479
|
+
<A>(that: Option<A>): <B>(self: Option<(a: A) => B>) => Option<B>
|
|
1480
|
+
<A, B>(self: Option<(a: A) => B>, that: Option<A>): Option<B>
|
|
1481
|
+
} = dual(2, <A, B>(self: Option<(a: A) => B>, that: Option<A>): Option<B> => zipWith(self, that, (f, a) => f(a)))
|
|
1482
|
+
|
|
1483
|
+
/**
|
|
1484
|
+
* Reduces an `Iterable` of `Option<A>` to a single value of type `B`, ignoring
|
|
1485
|
+
* elements that are `None`.
|
|
1486
|
+
*
|
|
1487
|
+
* **Details**
|
|
1488
|
+
*
|
|
1489
|
+
* This function takes an initial value of type `B` and a reducing function `f`
|
|
1490
|
+
* that combines the accumulator with values of type `A`. It processes an
|
|
1491
|
+
* iterable of `Option<A>`, applying `f` only to the `Some` values while
|
|
1492
|
+
* ignoring the `None` values. The result is a single value of type `B`.
|
|
1493
|
+
*
|
|
1494
|
+
* This utility is particularly useful for aggregating values from an iterable
|
|
1495
|
+
* of `Option`s while skipping the absent (`None`) values.
|
|
1496
|
+
*
|
|
1497
|
+
* @example
|
|
1498
|
+
* ```ts
|
|
1499
|
+
* import { Option, pipe } from "effect"
|
|
1500
|
+
*
|
|
1501
|
+
* const iterable = [Option.some(1), Option.none(), Option.some(2), Option.none()]
|
|
1502
|
+
*
|
|
1503
|
+
* console.log(pipe(iterable, Option.reduceCompact(0, (b, a) => b + a)))
|
|
1504
|
+
* // Output: 3
|
|
1505
|
+
* ```
|
|
1506
|
+
*
|
|
1507
|
+
* @category Reducing
|
|
1508
|
+
* @since 2.0.0
|
|
1509
|
+
*/
|
|
1510
|
+
export const reduceCompact: {
|
|
1511
|
+
<B, A>(b: B, f: (b: B, a: A) => B): (self: Iterable<Option<A>>) => B
|
|
1512
|
+
<A, B>(self: Iterable<Option<A>>, b: B, f: (b: B, a: A) => B): B
|
|
1513
|
+
} = dual(
|
|
1514
|
+
3,
|
|
1515
|
+
<A, B>(self: Iterable<Option<A>>, b: B, f: (b: B, a: A) => B): B => {
|
|
1516
|
+
let out: B = b
|
|
1517
|
+
for (const oa of self) {
|
|
1518
|
+
if (isSome(oa)) {
|
|
1519
|
+
out = f(out, oa.value)
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
return out
|
|
1523
|
+
}
|
|
1524
|
+
)
|
|
1525
|
+
|
|
1526
|
+
/**
|
|
1527
|
+
* Converts an `Option` into an `Array`.
|
|
1528
|
+
* If the input is `None`, an empty array is returned.
|
|
1529
|
+
* If the input is `Some`, its value is wrapped in a single-element array.
|
|
1530
|
+
*
|
|
1531
|
+
* @example
|
|
1532
|
+
* ```ts
|
|
1533
|
+
* import { Option } from "effect"
|
|
1534
|
+
*
|
|
1535
|
+
* console.log(Option.toArray(Option.some(1)))
|
|
1536
|
+
* // Output: [1]
|
|
1537
|
+
*
|
|
1538
|
+
* console.log(Option.toArray(Option.none()))
|
|
1539
|
+
* // Output: []
|
|
1540
|
+
* ```
|
|
1541
|
+
*
|
|
1542
|
+
* @category Conversions
|
|
1543
|
+
* @since 2.0.0
|
|
1544
|
+
*/
|
|
1545
|
+
export const toArray = <A>(self: Option<A>): Array<A> => isNone(self) ? [] : [self.value]
|
|
1546
|
+
|
|
1547
|
+
/**
|
|
1548
|
+
* Splits an `Option` into two `Option`s based on the result of a mapping
|
|
1549
|
+
* function that produces an `Either`.
|
|
1550
|
+
*
|
|
1551
|
+
* **Details**
|
|
1552
|
+
*
|
|
1553
|
+
* This function takes an `Option` and a mapping function `f` that converts its
|
|
1554
|
+
* value into an `Either`. It returns a tuple of two `Option`s:
|
|
1555
|
+
*
|
|
1556
|
+
* - The first `Option` (`left`) contains the value from the `Left` side of the
|
|
1557
|
+
* `Either` if it exists, otherwise `None`.
|
|
1558
|
+
* - The second `Option` (`right`) contains the value from the `Right` side of
|
|
1559
|
+
* the `Either` if it exists, otherwise `None`.
|
|
1560
|
+
*
|
|
1561
|
+
* If the input `Option` is `None`, both returned `Option`s are `None`.
|
|
1562
|
+
*
|
|
1563
|
+
* This utility is useful for filtering and categorizing the contents of an
|
|
1564
|
+
* `Option` based on a bifurcating computation.
|
|
1565
|
+
*
|
|
1566
|
+
* @category Filtering
|
|
1567
|
+
* @since 2.0.0
|
|
1568
|
+
*/
|
|
1569
|
+
export const partitionMap: {
|
|
1570
|
+
<A, B, C>(f: (a: A) => Either<C, B>): (self: Option<A>) => [left: Option<B>, right: Option<C>]
|
|
1571
|
+
<A, B, C>(self: Option<A>, f: (a: A) => Either<C, B>): [left: Option<B>, right: Option<C>]
|
|
1572
|
+
} = dual(2, <A, B, C>(
|
|
1573
|
+
self: Option<A>,
|
|
1574
|
+
f: (a: A) => Either<C, B>
|
|
1575
|
+
): [excluded: Option<B>, satisfying: Option<C>] => {
|
|
1576
|
+
if (isNone(self)) {
|
|
1577
|
+
return [none(), none()]
|
|
1578
|
+
}
|
|
1579
|
+
const e = f(self.value)
|
|
1580
|
+
return either.isLeft(e) ? [some(e.left), none()] : [none(), some(e.right)]
|
|
1581
|
+
})
|
|
1582
|
+
|
|
1583
|
+
// TODO(4.0): remove?
|
|
1584
|
+
/**
|
|
1585
|
+
* Alias of {@link flatMap}.
|
|
1586
|
+
*
|
|
1587
|
+
* @example
|
|
1588
|
+
* ```ts
|
|
1589
|
+
* import { Option } from "effect"
|
|
1590
|
+
*
|
|
1591
|
+
* // Transform and filter numbers
|
|
1592
|
+
* const transformEven = (n: Option.Option<number>): Option.Option<string> =>
|
|
1593
|
+
* Option.filterMap(n, (n) => (n % 2 === 0 ? Option.some(`Even: ${n}`) : Option.none()))
|
|
1594
|
+
*
|
|
1595
|
+
* console.log(transformEven(Option.none()))
|
|
1596
|
+
* // Output: { _id: 'Option', _tag: 'None' }
|
|
1597
|
+
*
|
|
1598
|
+
* console.log(transformEven(Option.some(1)))
|
|
1599
|
+
* // Output: { _id: 'Option', _tag: 'None' }
|
|
1600
|
+
*
|
|
1601
|
+
* console.log(transformEven(Option.some(2)))
|
|
1602
|
+
* // Output: { _id: 'Option', _tag: 'Some', value: 'Even: 2' }
|
|
1603
|
+
* ```
|
|
1604
|
+
*
|
|
1605
|
+
* @category Filtering
|
|
1606
|
+
* @since 2.0.0
|
|
1607
|
+
*/
|
|
1608
|
+
export const filterMap: {
|
|
1609
|
+
<A, B>(f: (a: A) => Option<B>): (self: Option<A>) => Option<B>
|
|
1610
|
+
<A, B>(self: Option<A>, f: (a: A) => Option<B>): Option<B>
|
|
1611
|
+
} = flatMap
|
|
1612
|
+
|
|
1613
|
+
/**
|
|
1614
|
+
* Filters an `Option` using a predicate. If the predicate is not satisfied or the `Option` is `None` returns `None`.
|
|
1615
|
+
*
|
|
1616
|
+
* If you need to change the type of the `Option` in addition to filtering, see `filterMap`.
|
|
1617
|
+
*
|
|
1618
|
+
* @example
|
|
1619
|
+
* ```ts
|
|
1620
|
+
* import { Option } from "effect"
|
|
1621
|
+
*
|
|
1622
|
+
* const removeEmptyString = (input: Option.Option<string>) =>
|
|
1623
|
+
* Option.filter(input, (value) => value !== "")
|
|
1624
|
+
*
|
|
1625
|
+
* console.log(removeEmptyString(Option.none()))
|
|
1626
|
+
* // Output: { _id: 'Option', _tag: 'None' }
|
|
1627
|
+
*
|
|
1628
|
+
* console.log(removeEmptyString(Option.some("")))
|
|
1629
|
+
* // Output: { _id: 'Option', _tag: 'None' }
|
|
1630
|
+
*
|
|
1631
|
+
* console.log(removeEmptyString(Option.some("a")))
|
|
1632
|
+
* // Output: { _id: 'Option', _tag: 'Some', value: 'a' }
|
|
1633
|
+
* ```
|
|
1634
|
+
*
|
|
1635
|
+
* @category Filtering
|
|
1636
|
+
* @since 2.0.0
|
|
1637
|
+
*/
|
|
1638
|
+
export const filter: {
|
|
1639
|
+
<A, B extends A>(refinement: Refinement<NoInfer<A>, B>): (self: Option<A>) => Option<B>
|
|
1640
|
+
<A>(predicate: Predicate<NoInfer<A>>): (self: Option<A>) => Option<A>
|
|
1641
|
+
<A, B extends A>(self: Option<A>, refinement: Refinement<A, B>): Option<B>
|
|
1642
|
+
<A>(self: Option<A>, predicate: Predicate<A>): Option<A>
|
|
1643
|
+
} = dual(
|
|
1644
|
+
2,
|
|
1645
|
+
<A>(self: Option<A>, predicate: Predicate<A>): Option<A> =>
|
|
1646
|
+
filterMap(self, (b) => (predicate(b) ? option.some(b) : option.none))
|
|
1647
|
+
)
|
|
1648
|
+
|
|
1649
|
+
/**
|
|
1650
|
+
* Creates an `Equivalence` instance for comparing `Option` values, using a
|
|
1651
|
+
* provided `Equivalence` for the inner type.
|
|
1652
|
+
*
|
|
1653
|
+
* **Details**
|
|
1654
|
+
*
|
|
1655
|
+
* This function takes an `Equivalence` instance for a specific type `A` and
|
|
1656
|
+
* produces an `Equivalence` instance for `Option<A>`. The resulting
|
|
1657
|
+
* `Equivalence` determines whether two `Option` values are equivalent:
|
|
1658
|
+
*
|
|
1659
|
+
* - Two `None`s are considered equivalent.
|
|
1660
|
+
* - A `Some` and a `None` are not equivalent.
|
|
1661
|
+
* - Two `Some` values are equivalent if their inner values are equivalent
|
|
1662
|
+
* according to the provided `Equivalence`.
|
|
1663
|
+
*
|
|
1664
|
+
* **Example** (Comparing Optional Numbers for Equivalence)
|
|
1665
|
+
*
|
|
1666
|
+
* ```ts
|
|
1667
|
+
* import { Number, Option } from "effect"
|
|
1668
|
+
*
|
|
1669
|
+
* const isEquivalent = Option.getEquivalence(Number.Equivalence)
|
|
1670
|
+
*
|
|
1671
|
+
* console.log(isEquivalent(Option.none(), Option.none()))
|
|
1672
|
+
* // Output: true
|
|
1673
|
+
*
|
|
1674
|
+
* console.log(isEquivalent(Option.none(), Option.some(1)))
|
|
1675
|
+
* // Output: false
|
|
1676
|
+
*
|
|
1677
|
+
* console.log(isEquivalent(Option.some(1), Option.none()))
|
|
1678
|
+
* // Output: false
|
|
1679
|
+
*
|
|
1680
|
+
* console.log(isEquivalent(Option.some(1), Option.some(2)))
|
|
1681
|
+
* // Output: false
|
|
1682
|
+
*
|
|
1683
|
+
* console.log(isEquivalent(Option.some(1), Option.some(1)))
|
|
1684
|
+
* // Output: true
|
|
1685
|
+
* ```
|
|
1686
|
+
*
|
|
1687
|
+
* @category Equivalence
|
|
1688
|
+
* @since 2.0.0
|
|
1689
|
+
*/
|
|
1690
|
+
export const getEquivalence = <A>(isEquivalent: Equivalence.Equivalence<A>): Equivalence.Equivalence<Option<A>> =>
|
|
1691
|
+
Equivalence.make((x, y) => isNone(x) ? isNone(y) : isNone(y) ? false : isEquivalent(x.value, y.value))
|
|
1692
|
+
|
|
1693
|
+
/**
|
|
1694
|
+
* Creates an `Order` instance for comparing `Option` values, using a provided
|
|
1695
|
+
* `Order` for the inner type.
|
|
1696
|
+
*
|
|
1697
|
+
* **Details**
|
|
1698
|
+
*
|
|
1699
|
+
* This function produces an `Order` instance for `Option<A>`, allowing `Option`
|
|
1700
|
+
* values to be compared:
|
|
1701
|
+
*
|
|
1702
|
+
* - `None` is always considered less than any `Some` value.
|
|
1703
|
+
* - If both are `Some`, their inner values are compared using the provided
|
|
1704
|
+
* `Order` instance.
|
|
1705
|
+
*
|
|
1706
|
+
* @example
|
|
1707
|
+
* ```ts
|
|
1708
|
+
* import { Number, Option } from "effect"
|
|
1709
|
+
*
|
|
1710
|
+
* const order = Option.getOrder(Number.Order)
|
|
1711
|
+
*
|
|
1712
|
+
* console.log(order(Option.none(), Option.none()))
|
|
1713
|
+
* // Output: 0
|
|
1714
|
+
*
|
|
1715
|
+
* console.log(order(Option.none(), Option.some(1)))
|
|
1716
|
+
* // Output: -1
|
|
1717
|
+
*
|
|
1718
|
+
* console.log(order(Option.some(1), Option.none()))
|
|
1719
|
+
* // Output: 1
|
|
1720
|
+
*
|
|
1721
|
+
* console.log(order(Option.some(1), Option.some(2)))
|
|
1722
|
+
* // Output: -1
|
|
1723
|
+
*
|
|
1724
|
+
* console.log(order(Option.some(1), Option.some(1)))
|
|
1725
|
+
* // Output: 0
|
|
1726
|
+
* ```
|
|
1727
|
+
*
|
|
1728
|
+
* @category Sorting
|
|
1729
|
+
* @since 2.0.0
|
|
1730
|
+
*/
|
|
1731
|
+
export const getOrder = <A>(O: Order<A>): Order<Option<A>> =>
|
|
1732
|
+
order.make((self, that) => isSome(self) ? (isSome(that) ? O(self.value, that.value) : 1) : -1)
|
|
1733
|
+
|
|
1734
|
+
/**
|
|
1735
|
+
* Lifts a binary function to work with `Option` values, allowing the function
|
|
1736
|
+
* to operate on two `Option`s.
|
|
1737
|
+
*
|
|
1738
|
+
* **Details**
|
|
1739
|
+
*
|
|
1740
|
+
* This function takes a binary function `f` and returns a new function that
|
|
1741
|
+
* applies `f` to the values of two `Option`s (`self` and `that`). If both
|
|
1742
|
+
* `Option`s are `Some`, the binary function `f` is applied to their values, and
|
|
1743
|
+
* the result is wrapped in a new `Some`. If either `Option` is `None`, the
|
|
1744
|
+
* result is `None`.
|
|
1745
|
+
*
|
|
1746
|
+
* @example
|
|
1747
|
+
* ```ts
|
|
1748
|
+
* import { Option } from "effect"
|
|
1749
|
+
*
|
|
1750
|
+
* // A binary function to add two numbers
|
|
1751
|
+
* const add = (a: number, b: number): number => a + b
|
|
1752
|
+
*
|
|
1753
|
+
* // Lift the `add` function to work with `Option` values
|
|
1754
|
+
* const addOptions = Option.lift2(add)
|
|
1755
|
+
*
|
|
1756
|
+
* // Both `Option`s are `Some`
|
|
1757
|
+
* console.log(addOptions(Option.some(2), Option.some(3)))
|
|
1758
|
+
* // Output: { _id: 'Option', _tag: 'Some', value: 5 }
|
|
1759
|
+
*
|
|
1760
|
+
* // One `Option` is `None`
|
|
1761
|
+
* console.log(addOptions(Option.some(2), Option.none()))
|
|
1762
|
+
* // Output: { _id: 'Option', _tag: 'None' }
|
|
1763
|
+
* ```
|
|
1764
|
+
*
|
|
1765
|
+
* @category Lifting
|
|
1766
|
+
* @since 2.0.0
|
|
1767
|
+
*/
|
|
1768
|
+
export const lift2 = <A, B, C>(f: (a: A, b: B) => C): {
|
|
1769
|
+
(that: Option<B>): (self: Option<A>) => Option<C>
|
|
1770
|
+
(self: Option<A>, that: Option<B>): Option<C>
|
|
1771
|
+
} => dual(2, (self: Option<A>, that: Option<B>): Option<C> => zipWith(self, that, f))
|
|
1772
|
+
|
|
1773
|
+
/**
|
|
1774
|
+
* Lifts a `Predicate` or `Refinement` into the `Option` context, returning a
|
|
1775
|
+
* `Some` of the input value if the predicate is satisfied, or `None` otherwise.
|
|
1776
|
+
*
|
|
1777
|
+
* **Details**
|
|
1778
|
+
*
|
|
1779
|
+
* This function transforms a `Predicate` (or a more specific `Refinement`) into
|
|
1780
|
+
* a function that produces an `Option`. If the predicate evaluates to `true`,
|
|
1781
|
+
* the input value is wrapped in a `Some`. If the predicate evaluates to
|
|
1782
|
+
* `false`, the result is `None`.
|
|
1783
|
+
*
|
|
1784
|
+
* @example
|
|
1785
|
+
* ```ts
|
|
1786
|
+
* import { Option } from "effect"
|
|
1787
|
+
*
|
|
1788
|
+
* // Check if a number is positive
|
|
1789
|
+
* const isPositive = (n: number) => n > 0
|
|
1790
|
+
*
|
|
1791
|
+
* // ┌─── (b: number) => Option<number>
|
|
1792
|
+
* // ▼
|
|
1793
|
+
* const parsePositive = Option.liftPredicate(isPositive)
|
|
1794
|
+
*
|
|
1795
|
+
* console.log(parsePositive(1))
|
|
1796
|
+
* // Output: { _id: 'Option', _tag: 'Some', value: 1 }
|
|
1797
|
+
*
|
|
1798
|
+
* console.log(parsePositive(-1))
|
|
1799
|
+
* // OUtput: { _id: 'Option', _tag: 'None' }
|
|
1800
|
+
* ```
|
|
1801
|
+
*
|
|
1802
|
+
* @category Lifting
|
|
1803
|
+
* @since 2.0.0
|
|
1804
|
+
*/
|
|
1805
|
+
export const liftPredicate: { // Note: I intentionally avoid using the NoInfer pattern here.
|
|
1806
|
+
<A, B extends A>(refinement: Refinement<A, B>): (a: A) => Option<B>
|
|
1807
|
+
<B extends A, A = B>(predicate: Predicate<A>): (b: B) => Option<B>
|
|
1808
|
+
<A, B extends A>(
|
|
1809
|
+
self: A,
|
|
1810
|
+
refinement: Refinement<A, B>
|
|
1811
|
+
): Option<B>
|
|
1812
|
+
<B extends A, A = B>(
|
|
1813
|
+
self: B,
|
|
1814
|
+
predicate: Predicate<A>
|
|
1815
|
+
): Option<B>
|
|
1816
|
+
} = dual(
|
|
1817
|
+
2,
|
|
1818
|
+
<B extends A, A = B>(b: B, predicate: Predicate<A>): Option<B> => predicate(b) ? some(b) : none()
|
|
1819
|
+
)
|
|
1820
|
+
|
|
1821
|
+
/**
|
|
1822
|
+
* Returns a function that checks if an `Option` contains a specified value,
|
|
1823
|
+
* using a provided equivalence function.
|
|
1824
|
+
*
|
|
1825
|
+
* **Details**
|
|
1826
|
+
*
|
|
1827
|
+
* This function allows you to check whether an `Option` contains a specific
|
|
1828
|
+
* value. It uses an equivalence function `isEquivalent` to compare the value
|
|
1829
|
+
* inside the `Option` to the provided value. If the `Option` is `Some` and the
|
|
1830
|
+
* equivalence function returns `true`, the result is `true`. If the `Option` is
|
|
1831
|
+
* `None` or the values are not equivalent, the result is `false`.
|
|
1832
|
+
*
|
|
1833
|
+
* @example
|
|
1834
|
+
* ```ts
|
|
1835
|
+
* import { Number, Option } from "effect"
|
|
1836
|
+
*
|
|
1837
|
+
* const contains = Option.containsWith(Number.Equivalence)
|
|
1838
|
+
*
|
|
1839
|
+
* console.log(Option.some(2).pipe(contains(2)))
|
|
1840
|
+
* // Output: true
|
|
1841
|
+
*
|
|
1842
|
+
* console.log(Option.some(1).pipe(contains(2)))
|
|
1843
|
+
* // Output: false
|
|
1844
|
+
*
|
|
1845
|
+
* console.log(Option.none().pipe(contains(2)))
|
|
1846
|
+
* // Output: false
|
|
1847
|
+
* ```
|
|
1848
|
+
*
|
|
1849
|
+
* @see {@link contains} for a version that uses the default `Equivalence`.
|
|
1850
|
+
*
|
|
1851
|
+
* @category Elements
|
|
1852
|
+
* @since 2.0.0
|
|
1853
|
+
*/
|
|
1854
|
+
export const containsWith = <A>(isEquivalent: (self: A, that: A) => boolean): {
|
|
1855
|
+
(a: A): (self: Option<A>) => boolean
|
|
1856
|
+
(self: Option<A>, a: A): boolean
|
|
1857
|
+
} => dual(2, (self: Option<A>, a: A): boolean => isNone(self) ? false : isEquivalent(self.value, a))
|
|
1858
|
+
|
|
1859
|
+
const _equivalence = Equal.equivalence()
|
|
1860
|
+
|
|
1861
|
+
/**
|
|
1862
|
+
* Returns a function that checks if an `Option` contains a specified value
|
|
1863
|
+
* using the default `Equivalence`.
|
|
1864
|
+
*
|
|
1865
|
+
* **Details**
|
|
1866
|
+
*
|
|
1867
|
+
* This function allows you to check whether an `Option` contains a specific
|
|
1868
|
+
* value. It uses the default `Equivalence` for equality comparison. If the
|
|
1869
|
+
* `Option` is `Some` and its value is equivalent to the provided value, the
|
|
1870
|
+
* result is `true`. If the `Option` is `None` or the values are not equivalent,
|
|
1871
|
+
* the result is `false`.
|
|
1872
|
+
*
|
|
1873
|
+
* @example
|
|
1874
|
+
* ```ts
|
|
1875
|
+
* import { Option } from "effect"
|
|
1876
|
+
*
|
|
1877
|
+
* console.log(Option.some(2).pipe(Option.contains(2)))
|
|
1878
|
+
* // Output: true
|
|
1879
|
+
*
|
|
1880
|
+
* console.log(Option.some(1).pipe(Option.contains(2)))
|
|
1881
|
+
* // Output: false
|
|
1882
|
+
*
|
|
1883
|
+
* console.log(Option.none().pipe(Option.contains(2)))
|
|
1884
|
+
* // Output: false
|
|
1885
|
+
* ```
|
|
1886
|
+
*
|
|
1887
|
+
* @see {@link containsWith} for a version that allows you to specify a custom equivalence function.
|
|
1888
|
+
*
|
|
1889
|
+
* @category Elements
|
|
1890
|
+
* @since 2.0.0
|
|
1891
|
+
*/
|
|
1892
|
+
export const contains: {
|
|
1893
|
+
<A>(a: A): (self: Option<A>) => boolean
|
|
1894
|
+
<A>(self: Option<A>, a: A): boolean
|
|
1895
|
+
} = containsWith(_equivalence)
|
|
1896
|
+
|
|
1897
|
+
/**
|
|
1898
|
+
* Checks if a value in an `Option` satisfies a given predicate or refinement.
|
|
1899
|
+
*
|
|
1900
|
+
* **Details**
|
|
1901
|
+
*
|
|
1902
|
+
* This function allows you to check if a value inside a `Some` meets a
|
|
1903
|
+
* specified condition. If the `Option` is `None`, the result is `false`. If the
|
|
1904
|
+
* `Option` is `Some`, the provided predicate or refinement is applied to the
|
|
1905
|
+
* value:
|
|
1906
|
+
*
|
|
1907
|
+
* - If the condition is met, the result is `true`.
|
|
1908
|
+
* - If the condition is not met, the result is `false`.
|
|
1909
|
+
*
|
|
1910
|
+
* @example
|
|
1911
|
+
* ```ts
|
|
1912
|
+
* import { Option } from "effect"
|
|
1913
|
+
*
|
|
1914
|
+
* const isEven = (n: number) => n % 2 === 0
|
|
1915
|
+
*
|
|
1916
|
+
* console.log(Option.some(2).pipe(Option.exists(isEven)))
|
|
1917
|
+
* // Output: true
|
|
1918
|
+
*
|
|
1919
|
+
* console.log(Option.some(1).pipe(Option.exists(isEven)))
|
|
1920
|
+
* // Output: false
|
|
1921
|
+
*
|
|
1922
|
+
* console.log(Option.none().pipe(Option.exists(isEven)))
|
|
1923
|
+
* // Output: false
|
|
1924
|
+
* ```
|
|
1925
|
+
*
|
|
1926
|
+
* @category Elements
|
|
1927
|
+
* @since 2.0.0
|
|
1928
|
+
*/
|
|
1929
|
+
export const exists: {
|
|
1930
|
+
<A, B extends A>(refinement: Refinement<NoInfer<A>, B>): (self: Option<A>) => self is Option<B>
|
|
1931
|
+
<A>(predicate: Predicate<NoInfer<A>>): (self: Option<A>) => boolean
|
|
1932
|
+
<A, B extends A>(self: Option<A>, refinement: Refinement<A, B>): self is Option<B>
|
|
1933
|
+
<A>(self: Option<A>, predicate: Predicate<A>): boolean
|
|
1934
|
+
} = dual(
|
|
1935
|
+
2,
|
|
1936
|
+
<A, B extends A>(self: Option<A>, refinement: Refinement<A, B>): self is Option<B> =>
|
|
1937
|
+
isNone(self) ? false : refinement(self.value)
|
|
1938
|
+
)
|
|
1939
|
+
|
|
1940
|
+
// -------------------------------------------------------------------------------------
|
|
1941
|
+
// do notation
|
|
1942
|
+
// -------------------------------------------------------------------------------------
|
|
1943
|
+
|
|
1944
|
+
/**
|
|
1945
|
+
* The "do simulation" in Effect allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
|
|
1946
|
+
*
|
|
1947
|
+
* Here's how the do simulation works:
|
|
1948
|
+
*
|
|
1949
|
+
* 1. Start the do simulation using the `Do` value
|
|
1950
|
+
* 2. Within the do simulation scope, you can use the `bind` function to define variables and bind them to `Option` values
|
|
1951
|
+
* 3. You can accumulate multiple `bind` statements to define multiple variables within the scope
|
|
1952
|
+
* 4. Inside the do simulation scope, you can also use the `let` function to define variables and bind them to simple values
|
|
1953
|
+
* 5. Regular `Option` functions like `map` and `filter` can still be used within the do simulation. These functions will receive the accumulated variables as arguments within the scope
|
|
1954
|
+
*
|
|
1955
|
+
* @example
|
|
1956
|
+
* ```ts
|
|
1957
|
+
* import * as assert from "node:assert"
|
|
1958
|
+
* import { Option, pipe } from "effect"
|
|
1959
|
+
*
|
|
1960
|
+
* const result = pipe(
|
|
1961
|
+
* Option.Do,
|
|
1962
|
+
* Option.bind("x", () => Option.some(2)),
|
|
1963
|
+
* Option.bind("y", () => Option.some(3)),
|
|
1964
|
+
* Option.let("sum", ({ x, y }) => x + y),
|
|
1965
|
+
* Option.filter(({ x, y }) => x * y > 5)
|
|
1966
|
+
* )
|
|
1967
|
+
* assert.deepStrictEqual(result, Option.some({ x: 2, y: 3, sum: 5 }))
|
|
1968
|
+
* ```
|
|
1969
|
+
*
|
|
1970
|
+
* @see {@link Do}
|
|
1971
|
+
* @see {@link bind}
|
|
1972
|
+
* @see {@link let_ let}
|
|
1973
|
+
*
|
|
1974
|
+
* @category Do notation
|
|
1975
|
+
* @since 2.0.0
|
|
1976
|
+
*/
|
|
1977
|
+
export const bindTo: {
|
|
1978
|
+
<N extends string>(name: N): <A>(self: Option<A>) => Option<{ [K in N]: A }>
|
|
1979
|
+
<A, N extends string>(self: Option<A>, name: N): Option<{ [K in N]: A }>
|
|
1980
|
+
} = doNotation.bindTo<OptionTypeLambda>(map)
|
|
1981
|
+
|
|
1982
|
+
const let_: {
|
|
1983
|
+
<N extends string, A extends object, B>(
|
|
1984
|
+
name: Exclude<N, keyof A>,
|
|
1985
|
+
f: (a: NoInfer<A>) => B
|
|
1986
|
+
): (self: Option<A>) => Option<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }>
|
|
1987
|
+
<A extends object, N extends string, B>(
|
|
1988
|
+
self: Option<A>,
|
|
1989
|
+
name: Exclude<N, keyof A>,
|
|
1990
|
+
f: (a: NoInfer<A>) => B
|
|
1991
|
+
): Option<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }>
|
|
1992
|
+
} = doNotation.let_<OptionTypeLambda>(map)
|
|
1993
|
+
|
|
1994
|
+
export {
|
|
1995
|
+
/**
|
|
1996
|
+
* The "do simulation" in Effect allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
|
|
1997
|
+
*
|
|
1998
|
+
* Here's how the do simulation works:
|
|
1999
|
+
*
|
|
2000
|
+
* 1. Start the do simulation using the `Do` value
|
|
2001
|
+
* 2. Within the do simulation scope, you can use the `bind` function to define variables and bind them to `Option` values
|
|
2002
|
+
* 3. You can accumulate multiple `bind` statements to define multiple variables within the scope
|
|
2003
|
+
* 4. Inside the do simulation scope, you can also use the `let` function to define variables and bind them to simple values
|
|
2004
|
+
* 5. Regular `Option` functions like `map` and `filter` can still be used within the do simulation. These functions will receive the accumulated variables as arguments within the scope
|
|
2005
|
+
*
|
|
2006
|
+
* @example
|
|
2007
|
+
* ```ts
|
|
2008
|
+
* import * as assert from "node:assert"
|
|
2009
|
+
* import { Option, pipe } from "effect"
|
|
2010
|
+
*
|
|
2011
|
+
* const result = pipe(
|
|
2012
|
+
* Option.Do,
|
|
2013
|
+
* Option.bind("x", () => Option.some(2)),
|
|
2014
|
+
* Option.bind("y", () => Option.some(3)),
|
|
2015
|
+
* Option.let("sum", ({ x, y }) => x + y),
|
|
2016
|
+
* Option.filter(({ x, y }) => x * y > 5)
|
|
2017
|
+
* )
|
|
2018
|
+
* assert.deepStrictEqual(result, Option.some({ x: 2, y: 3, sum: 5 }))
|
|
2019
|
+
* ```
|
|
2020
|
+
*
|
|
2021
|
+
* @see {@link Do}
|
|
2022
|
+
* @see {@link bind}
|
|
2023
|
+
* @see {@link bindTo}
|
|
2024
|
+
*
|
|
2025
|
+
* @category Do notation
|
|
2026
|
+
* @since 2.0.0
|
|
2027
|
+
*/
|
|
2028
|
+
let_ as let
|
|
2029
|
+
}
|
|
2030
|
+
|
|
2031
|
+
/**
|
|
2032
|
+
* The "do simulation" in Effect allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
|
|
2033
|
+
*
|
|
2034
|
+
* Here's how the do simulation works:
|
|
2035
|
+
*
|
|
2036
|
+
* 1. Start the do simulation using the `Do` value
|
|
2037
|
+
* 2. Within the do simulation scope, you can use the `bind` function to define variables and bind them to `Option` values
|
|
2038
|
+
* 3. You can accumulate multiple `bind` statements to define multiple variables within the scope
|
|
2039
|
+
* 4. Inside the do simulation scope, you can also use the `let` function to define variables and bind them to simple values
|
|
2040
|
+
* 5. Regular `Option` functions like `map` and `filter` can still be used within the do simulation. These functions will receive the accumulated variables as arguments within the scope
|
|
2041
|
+
*
|
|
2042
|
+
* @example
|
|
2043
|
+
* ```ts
|
|
2044
|
+
* import * as assert from "node:assert"
|
|
2045
|
+
* import { Option, pipe } from "effect"
|
|
2046
|
+
*
|
|
2047
|
+
* const result = pipe(
|
|
2048
|
+
* Option.Do,
|
|
2049
|
+
* Option.bind("x", () => Option.some(2)),
|
|
2050
|
+
* Option.bind("y", () => Option.some(3)),
|
|
2051
|
+
* Option.let("sum", ({ x, y }) => x + y),
|
|
2052
|
+
* Option.filter(({ x, y }) => x * y > 5)
|
|
2053
|
+
* )
|
|
2054
|
+
* assert.deepStrictEqual(result, Option.some({ x: 2, y: 3, sum: 5 }))
|
|
2055
|
+
* ```
|
|
2056
|
+
*
|
|
2057
|
+
* @see {@link Do}
|
|
2058
|
+
* @see {@link bindTo}
|
|
2059
|
+
* @see {@link let_ let}
|
|
2060
|
+
*
|
|
2061
|
+
* @category Do notation
|
|
2062
|
+
* @since 2.0.0
|
|
2063
|
+
*/
|
|
2064
|
+
export const bind: {
|
|
2065
|
+
<N extends string, A extends object, B>(
|
|
2066
|
+
name: Exclude<N, keyof A>,
|
|
2067
|
+
f: (a: NoInfer<A>) => Option<B>
|
|
2068
|
+
): (self: Option<A>) => Option<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }>
|
|
2069
|
+
<A extends object, N extends string, B>(
|
|
2070
|
+
self: Option<A>,
|
|
2071
|
+
name: Exclude<N, keyof A>,
|
|
2072
|
+
f: (a: NoInfer<A>) => Option<B>
|
|
2073
|
+
): Option<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }>
|
|
2074
|
+
} = doNotation.bind<OptionTypeLambda>(map, flatMap)
|
|
2075
|
+
|
|
2076
|
+
/**
|
|
2077
|
+
* The "do simulation" in Effect allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
|
|
2078
|
+
*
|
|
2079
|
+
* Here's how the do simulation works:
|
|
2080
|
+
*
|
|
2081
|
+
* 1. Start the do simulation using the `Do` value
|
|
2082
|
+
* 2. Within the do simulation scope, you can use the `bind` function to define variables and bind them to `Option` values
|
|
2083
|
+
* 3. You can accumulate multiple `bind` statements to define multiple variables within the scope
|
|
2084
|
+
* 4. Inside the do simulation scope, you can also use the `let` function to define variables and bind them to simple values
|
|
2085
|
+
* 5. Regular `Option` functions like `map` and `filter` can still be used within the do simulation. These functions will receive the accumulated variables as arguments within the scope
|
|
2086
|
+
*
|
|
2087
|
+
* @example
|
|
2088
|
+
* ```ts
|
|
2089
|
+
* import * as assert from "node:assert"
|
|
2090
|
+
* import { Option, pipe } from "effect"
|
|
2091
|
+
*
|
|
2092
|
+
* const result = pipe(
|
|
2093
|
+
* Option.Do,
|
|
2094
|
+
* Option.bind("x", () => Option.some(2)),
|
|
2095
|
+
* Option.bind("y", () => Option.some(3)),
|
|
2096
|
+
* Option.let("sum", ({ x, y }) => x + y),
|
|
2097
|
+
* Option.filter(({ x, y }) => x * y > 5)
|
|
2098
|
+
* )
|
|
2099
|
+
* assert.deepStrictEqual(result, Option.some({ x: 2, y: 3, sum: 5 }))
|
|
2100
|
+
* ```
|
|
2101
|
+
*
|
|
2102
|
+
* @see {@link bindTo}
|
|
2103
|
+
* @see {@link bind}
|
|
2104
|
+
* @see {@link let_ let}
|
|
2105
|
+
*
|
|
2106
|
+
* @category Do notation
|
|
2107
|
+
* @since 2.0.0
|
|
2108
|
+
*/
|
|
2109
|
+
export const Do: Option<{}> = some({})
|
|
2110
|
+
|
|
2111
|
+
const adapter = Gen.adapter<OptionTypeLambda>()
|
|
2112
|
+
|
|
2113
|
+
/**
|
|
2114
|
+
* Similar to `Effect.gen`, `Option.gen` provides a more readable,
|
|
2115
|
+
* generator-based syntax for working with `Option` values, making code that
|
|
2116
|
+
* involves `Option` easier to write and understand. This approach is similar to
|
|
2117
|
+
* using `async/await` but tailored for `Option`.
|
|
2118
|
+
*
|
|
2119
|
+
* **Example** (Using `Option.gen` to Create a Combined Value)
|
|
2120
|
+
*
|
|
2121
|
+
* ```ts
|
|
2122
|
+
* import { Option } from "effect"
|
|
2123
|
+
*
|
|
2124
|
+
* const maybeName: Option.Option<string> = Option.some("John")
|
|
2125
|
+
* const maybeAge: Option.Option<number> = Option.some(25)
|
|
2126
|
+
*
|
|
2127
|
+
* const person = Option.gen(function* () {
|
|
2128
|
+
* const name = (yield* maybeName).toUpperCase()
|
|
2129
|
+
* const age = yield* maybeAge
|
|
2130
|
+
* return { name, age }
|
|
2131
|
+
* })
|
|
2132
|
+
*
|
|
2133
|
+
* console.log(person)
|
|
2134
|
+
* // Output:
|
|
2135
|
+
* // { _id: 'Option', _tag: 'Some', value: { name: 'JOHN', age: 25 } }
|
|
2136
|
+
* ```
|
|
2137
|
+
*
|
|
2138
|
+
* @category Generators
|
|
2139
|
+
* @since 2.0.0
|
|
2140
|
+
*/
|
|
2141
|
+
export const gen: Gen.Gen<OptionTypeLambda, Gen.Adapter<OptionTypeLambda>> = (...args) => {
|
|
2142
|
+
const f = args.length === 1 ? args[0] : args[1].bind(args[0])
|
|
2143
|
+
const iterator = f(adapter)
|
|
2144
|
+
let state: IteratorResult<any> = iterator.next()
|
|
2145
|
+
while (!state.done) {
|
|
2146
|
+
const current = Gen.isGenKind(state.value)
|
|
2147
|
+
? state.value.value
|
|
2148
|
+
: Gen.yieldWrapGet(state.value)
|
|
2149
|
+
if (isNone(current)) {
|
|
2150
|
+
return current
|
|
2151
|
+
}
|
|
2152
|
+
state = iterator.next(current.value as never)
|
|
2153
|
+
}
|
|
2154
|
+
return some(state.value)
|
|
2155
|
+
}
|
|
2156
|
+
|
|
2157
|
+
/**
|
|
2158
|
+
* Merges two optional values, applying a function if both exist.
|
|
2159
|
+
* Unlike {@link zipWith}, this function returns `None` only if both inputs are `None`.
|
|
2160
|
+
*
|
|
2161
|
+
* @internal
|
|
2162
|
+
*/
|
|
2163
|
+
export const mergeWith = <A>(f: (a1: A, a2: A) => A) => (o1: Option<A>, o2: Option<A>): Option<A> => {
|
|
2164
|
+
if (isNone(o1)) {
|
|
2165
|
+
return o2
|
|
2166
|
+
} else if (isNone(o2)) {
|
|
2167
|
+
return o1
|
|
2168
|
+
}
|
|
2169
|
+
return some(f(o1.value, o2.value))
|
|
2170
|
+
}
|