This Week in Effect - 2024-02-02
Hi Effecters! Welcome to the very first This Week In Effect (TWIE).
We’re proud to present you with this new format created to help you keep track of everything that is going on inside our Community and the Effect Ecosystem.
If it’s your first time here, Effect is a powerful TypeScript library designed to help developers create complex, synchronous, and asynchronous programs. One of the key features that sets Effect apart is how it leverages structured concurrency to provide features such as async cancellation and safe resource management, making it easier to build robust, scalable, and efficient programs.
To get started, below you’ll find our quick-start guide and documentation that will be your first step in your Effect journey. Enjoy!
Overview of TWIE
Before we get into what happened in the last week in our Community, we would like to say a few words about TWIE.
We’re happy to witness the community growing so fast, with more and more people adopting Effect, and we understand that it might not be that easy keeping up with everything that is going on in the Effect Ecosystem:
- Our Discord server reached 1850+ members a few days ago and the engagement is at an all-time high.
- We’re approaching our very first Effect Days Conference in Vienna on February 23, 2024, and lots of new content is coming up.
- All projects around Effect are receiving key updates and there has been a lot of activity on GitHub.
So, we wanted to make it easy for you to find all the info you need to fully enjoy your Effect journey!
And, that’s why we created TWIE – a weekly update to inform you about key events about Effect in the previous week, both from the community (Discord discussions, X posts, YouTube content etc.) and from a technical standpoint.
In this way, we want to help you stay on track with everything happening in the Effect Ecosystem and actively engage with our community.
So, let’s start!
Technology
Lists all the features, bug fixes, and changes (sometimes breaking) of this week.
General Chores
This adds provenance for publishing packages.
Effect Core
Add JSDoc documentation for Effect.intoDeferred
Improves performance of computing a FiberId hash by caching the computation
- Use TimeoutException for timeout (Breaking)
Use TimeoutException
for timeout, previously timeout used NoSuchElementException
and it proved to be confusing and error-prone when using combinators such as Effect.optionFromOptional
to recover from such exceptions.
The following code is now valid:
ts
import { Effect } from "effect"const recoverFromTimeout = Effect.sleep("2 seconds").pipe(Effect.timeout("1 second"),Effect.catchTag("TimeoutException", () =>Effect.log("The program timed out")))
ts
import { Effect } from "effect"const recoverFromTimeout = Effect.sleep("2 seconds").pipe(Effect.timeout("1 second"),Effect.catchTag("TimeoutException", () =>Effect.log("The program timed out")))
- Make Equal & Hash Implicit (Breaking)
With this change we remove the Data
type and we make Equal
& Hash
implicit traits.
The main reason is that Data<A>
was structurally equivalent to A & Equal
but extending Equal
doesn't mean that the equality is implemented by-value, so the type was simply adding noise without gaining any level of safety.
The module Data
remains unchanged at the value level, all the functions previously available are supposed to work in exactly the same manner.
At the type level instead the functions return Readonly
variants, so for example we have:
ts
import { Data } from "effect"const obj = Data.struct({a: 0,b: 1})
ts
import { Data } from "effect"const obj = Data.struct({a: 0,b: 1})
will have the obj
typed as:
ts
declare const obj: {readonly a: numberreadonly b: number}
ts
declare const obj: {readonly a: numberreadonly b: number}
- Improve naming for ReadonlyRecord (Breaking)
Improves naming of methods within the ReadonlyRecord
module. Specifically, it renames ReadonlyRecord.upsert
to ReadonlyRecord.set
and ReadonlyRecord.update
to ReadonlyRecord.replace
. It also adds a new ReadonlyRecord.modify
combinator that can be used to apply a function to the value of a ReadonlyRecord
at a specific key.
Effect Schema
Adds a new section to the project README that explains the annotations feature by showing how to customize the generation of Arbitrary<A>
instances.
Reorganizes overloads in Schema.optional
to improve development experience when specifying defaults.
Improves generation of Equivalence
supporting cases where schemas include transformations. Namely the following code:
ts
import { Schema } from "@effect/schema"const schema = S.NumberFromStringconst equivalence = E.make(schema)
ts
import { Schema } from "@effect/schema"const schema = S.NumberFromStringconst equivalence = E.make(schema)
No longer throws an error.
Add option
to preserve excess properties when parsing, the feature is described in detail in the issue and can be summarized as:
ts
const data = S.parseSync({foo: S.string})({foo: "ok",bar: "ok"})
ts
const data = S.parseSync({foo: S.string})({foo: "ok",bar: "ok"})
The above code will strip the bar
property as it is not defined in the schema, with the additional option as below:
ts
const data = S.parseSync({foo: S.string})({foo: "ok",bar: "ok"},{onExcessProperty: "preserve"})
ts
const data = S.parseSync({foo: S.string})({foo: "ok",bar: "ok"},{onExcessProperty: "preserve"})
The excess property is no longer removed.
- Reorder Schema Generics (Breaking)
Swaps the order of type parameters to simplify explicit type definitions, namely Schema<R, I, A>
becomes Schema<A, I = A, R = never>
this change also enables us to specify defaults for type parameters.
This enables to type simple schemas as:
ts
import { Schema } from "@effect/schema"declare const number: Schema<number>
ts
import { Schema } from "@effect/schema"declare const number: Schema<number>
and most importantly enables to ignore context when not needed like:
ts
import { Schema } from "@effect/schema"declare const numberFromString: Schema<number, string>
ts
import { Schema } from "@effect/schema"declare const numberFromString: Schema<number, string>
instead of being forced to write every parameter always like:
ts
import { Schema } from "@effect/schema"declare const number: Schema<never, number, number>
ts
import { Schema } from "@effect/schema"declare const number: Schema<never, number, number>
Effect Platform
Ensuring that fibers forked in uninterruptible regions are able to be interrupted.
Use Proxy
for platform schema Transferable
.
Adds support for URL objects in HTTP Client, the following code is now valid:
ts
import { HttpClientRequest, HttpClient } from "@effect/platform"import { Effect } from "effect"const request = HttpClientRequest.get(new URL("https://www.google.com/")).pipe(HttpClient.fetchOk,Effect.flatMap((_) => _.text))
ts
import { HttpClientRequest, HttpClient } from "@effect/platform"import { Effect } from "effect"const request = HttpClientRequest.get(new URL("https://www.google.com/")).pipe(HttpClient.fetchOk,Effect.flatMap((_) => _.text))
- Remove re-exports and rename packages (Breaking)
Removes re-exports from @effect/platform-*
packages and improves naming of specialized modules, generic modules like HttpClient
can now be imported only from @effect/platform
and specific modules like NodeRuntime
can be imported from the specific platform package (in this case @effect/platform-node
).
ts
import { Runtime } from "@effect/platform-node"
ts
import { Runtime } from "@effect/platform-node"
becomes:
ts
import { NodeRuntime } from "@effect/platform-node"
ts
import { NodeRuntime } from "@effect/platform-node"
and:
ts
import { HttpClient } from "@effect/platform-node"
ts
import { HttpClient } from "@effect/platform-node"
becomes:
ts
import { HttpClient } from "@effect/platform"
ts
import { HttpClient } from "@effect/platform"
- Fixes encoding of Transferable (Breaking)
Fixes encoding of Transferable schemas, breaking because it includes a type-level change.
Effect Experimental
Ensuring that fibers forked in uninterruptible regions are able to be interrupted.
Effect CLI
Ensures proper error reporting when a single input is provided to a variadic option. Prior, the check was silently skipped.
Fixes the README to update:
- introduction of the executable parameter as CLI no longer needs to slice
process.argv
and automatically deals with executable path; - adds missing
Args
from the README example.
Community
Guess what?! We welcomed 22 new Effecters last week! Thank you for joining the community and we look forward to your active participation in our ever-growing family!
Effect Days Update
Hear, hear! A big announcement from Vienna!
We've opened up 5 more spots for our Effect Days workshops on Feb 22nd! Both workshop and conference tickets are quickly running out, so don't miss the opportunity to grab your own!
The Conference is quickly approaching, and we presented our final speaker: Tim Smart, Effect Core Contributor and founding engineer of Effectful Technologies!
So, here you can find our full speakers lineup for Vienna: Speakers
Moreover, as the 23rd come closer, our speakers are giving a a short video sneak peek of their speeches.
Here you'll discover the one from Antoine Coulon:
and from Mattia Manzati:
Closing Notes
That's all for this week. Thank you for being a vital part of our community. Your feedback and requests are highly valued as we fine-tune this new format. Feel free to share your thoughts, and we'll do our best to tailor it to the needs of our community.
The Effect Community Team