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.
1import { FileSystem } from "@effect/platform"2import { NodeFileSystem } from "@effect/platform-node"3import type { Layer } from "effect"4import * as Effect from "effect/Effect"5
6export class Cache extends Effect.Service<Cache>()("app/Cache", {7 // define how to create the service8 // You can also use the "scoped", "sync" or "succeed" keys to create your service9 effect: Effect.gen(function* () {10 const fs = yield* FileSystem.FileSystem11 const lookup = (key: string) => fs.readFileString(`cache/${key}`)12 return { lookup } as const13 }),14 // provide dependencies15 dependencies: [NodeFileSystem.layer]16}) {}17
18// Layer for use in the application19const layer: Layer.Layer<Cache> = Cache.Default20
21// Layer without dependencies provided22const layerNoDeps: Layer.Layer<Cache, never, FileSystem.FileSystem> =23 Cache.DefaultWithoutDependencies24
25// `Cache` type also represents the service itself26declare const cache: Cache27cache.lookup("foo")
The Effect.provide
& Layer.provide
apis can now accept multiple layers to be provided.
1someEffect.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.
1import { Effect, Layer, ManagedRuntime } from "effect"2
3const runtime = ManagedRuntime.make(Layer.empty)4
5someEffect.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
.
1import { Predicate } from "effect"2
3assert.deepStrictEqual(Predicate.isRegExp(/a/), true)4assert.deepStrictEqual(Predicate.isRegExp("a"), false)
Tuple.map
can be used to transform each element of a tuple using a function.
1import { pipe, Tuple } from "effect"2
3const result = pipe(4 // ^? [string, string, string]5 ["a", 1, false] as const,6 Tuple.map((el) => {7 // ^? "a" | 1 | false8 return el.toString().toUpperCase()9 })10)11assert.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.
1import { Array } from "effect"2
3const arr = [1, 2, 3]4const result = Array.pad(arr, 6, 0)5assert.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!