Effect 3.9 (Release)
Effect 3.9 has been released! This release includes a number of new features and improvements. Here’s a summary of what’s new:
To make the creation of services in Effect easier, the Effect.Service
api has been introduced.
It allows you to define both a Context.Tag
and a Layer
for a service in one pass, optionally giving you
the ability to provide any dependencies at the same time.
import { FileSystem } from "@effect/platform"import { NodeFileSystem } from "@effect/platform-node"import type { Layer } from "effect"import * as Effect from "effect/Effect"
export class Cache extends Effect.Service<Cache>()("app/Cache", { // define how to create the service // You can also use the "scoped", "sync" or "succeed" keys to create your service effect: Effect.gen(function* () { const fs = yield* FileSystem.FileSystem const lookup = (key: string) => fs.readFileString(`cache/${key}`) return { lookup } as const }), // provide dependencies dependencies: [NodeFileSystem.layer]}) {}
// Layer for use in the applicationconst layer: Layer.Layer<Cache> = Cache.Default
// Layer without dependencies providedconst layerNoDeps: Layer.Layer<Cache, never, FileSystem.FileSystem> = Cache.DefaultWithoutDependencies
// `Cache` type also represents the service itselfdeclare const cache: Cachecache.lookup("foo")
The Effect.provide
& Layer.provide
apis can now accept multiple layers to be provided.
someEffect.pipe(Effect.provide([layer1, layer2, layer3]))
You can now provide a ManagedRuntime
to an effect, allowing you to use the
services from the ManagedRuntime
inside of the effect.
import { Effect, Layer, ManagedRuntime } from "effect"
const runtime = ManagedRuntime.make(Layer.empty)
someEffect.pipe(Effect.provide(runtime))
If you use a NonEmptyArray
with Effect.mapAccum
or Array.mapAccum
, the
result will now be typed as a NonEmptyArray
.
You can use this api to determine if a value is a RegExp
.
import { Predicate } from "effect"
assert.deepStrictEqual(Predicate.isRegExp(/a/), true)assert.deepStrictEqual(Predicate.isRegExp("a"), false)
Tuple.map
can be used to transform each element of a tuple using a function.
import { pipe, Tuple } from "effect"
const result = pipe( // ^? [string, string, string] ["a", 1, false] as const, Tuple.map((el) => { // ^? "a" | 1 | false return el.toString().toUpperCase() }))assert.deepStrictEqual(result, ["A", "1", "FALSE"])
This api can be used to add elements to the end of an array until it reaches the desired length.
import { Array } from "effect"
const arr = [1, 2, 3]const result = Array.pad(arr, 6, 0)assert.deepStrictEqual(result, [1, 2, 3, 0, 0, 0])
There were several other smaller changes made. Take a look through the CHANGELOG to see them all: CHANGELOG.
Don’t forget to join our Discord Community to follow the last updates and discuss every tiny detail!