Effect is maturing TypeScript's ecosystem by enforcing rigorous architectural patterns that prioritize long-term maintainability and type integrity. This session effectively demonstrates how to balance functional purity with practical developer experience through sophisticated error handling and improved tooling.
Deep Dive
Prerequisite Knowledge
- No data available.
Where to go next
- No data available.
Deep Dive
Effect Office Hours 30 🔥Added:
and we are indeed live it seems. Nice.
Hello everyone. Effect enjoyers, effect lovers, how's it going?
How are we going who's here today? Let's see. Let's see.
As you have may seen today, we are not joined by Maxwell. As we said last time, today you're all alone with me.
and let's see how it goes.
Let's wait a few minutes for people to tune in.
Hello, Dabbat.
Hope I pronounce it it well. I don't know.
Oh, I need to change one setting from Riverside. Going to go offline for a second. I'm going to be back.
Good day.
How's everyone going?
We should be back.
Okay, we should be live. Are we live?
Yes, I think so.
Just waiting for a confirmation that I am back online.
Okay.
So, let's see. Let's see.
So let's see together what we can deal with today. So have you all had a great week? How's everyone? Oh, welcome back.
Fifth fifth fifth fifth I don't I don't remember the pronunciation every time.
Oh, welcome back to Ar Jensen as well.
How's you? How's everyone going? So, have you shipped effect stuff in production last week? Last week, I hope so because I did. So, I hope you did as well.
So as always as I've prompted uh through the through the effect office our discord channel uh as always uh we are open for questions if there is some code snippets some g or some repo that you want us to go through I am more than happy to have a look at it and see and discuss with And if you have have question maybe we can go through them. And if not if not uh maybe we can do um something um similar something good to to show. Oh, we have our first question.
Uh let me just arrange my windows for a second. Let me do uh quite a few uh window management and then I'll start replying your questions.
So um uh let me check. Uh yes yes yes.
Okay. So okay so it seems that we are starting to have some questions. So uh let me see let me start from a few of them. So, Queser, hope I pronounce it correct asked, "One difficulty I often run into when writing effect is that hype overs and error overs can feel pretty cryptic and noisy. And sometimes I was just want to see what an FN takes over it. So much going on."
And so, let's see. Maybe I can share my screen with a repository.
Uh let me just check. Yes. No.
Okay. So one thing that you can use in order to get better content for your overs is the effect LSP which was something I have uh worked on. And one of the features of the effect LSP let me show share the screen first. Uh share share screen. uh entire screen this screen share.
Okay. So one thing that you can use for that is the effect language service which is available both for TypeScript Go if you are already using TypeScript Go or you can use the classic effect language service. And one of the features that um the language service provides over the other functions that they provide is the fact that you can hover um any effect type or yield star in an effect gen and you'll get a preier print of um the types parameter of your effect.
So, let me zoom in first. Uh, let me see if we can Yes. Is that enough?
Is that good enough screen screen size-wise?
And so, let me check if we have a project we can use to show that off.
So, uh let me let me see if we can uh increase my font size so I can show it live in in an editor.
Okay, so this is my project with DF effect LSP enabled. And as you can see in here, you already get better reading of your types because automatically what the effectless speed does is um whenever you have something that is an effect uh you automatically get uh this hover that also shows in clean separate types um the success, the failure and the requirement channel. And this is usually useful uh because uh first of all that is not truncated. And so um that not being truncated means that you see for example all of the errors that can happen. And um also it helps in cases the one you mentioned where you have maybe a complex type or or something that is a result of a call and then it it is usually hidden by uh the signature. But thanks to the effect LSP, you can see all of that.
And again, um there is uh a guide over the effect uh language service repository and also the TypeScript Go version to get started with it. But behind the scene, it's really simple. What you need to do is just to run uh for the go version MPX effects go setup and that will go through uh an automated setup that will perform uh the installation step steps you need in order to get that running.
So hope that feature uh helps you and also hope that I answered your question.
So um as a followup is is this mostly a skill issues I'm not familiar enough with that patterns yet or is this a real DX problem with Ali type libraries uh with effect well as you can see and as I haven't shown that is basically due to how the library is well typed and in order to make that hover more meaningful the LSP helps by extracting the domain meanings of your type and show them uh right alongside of your type and I have to explain one of my friends the effect like simple explanation or example to blow their mind.
So this is a question uh that we often get. How can I basically present to someone effect and how we can um leverage um things that can be show off from effect from one user that comes from playing TPScript and we want to explain the values of effect. Well, I would say that there are different approaches to that and the different approaches uh basically um take different parts of effect based on what's the purpose of your application. For example, things like type safety, type error channel. To me, they are sure a good part of effect, but they are not the only reason for why one should adopt effect. One, for example, should adopt effect because, for example, it has built-in telemetry primitives. And I challenge you to write a full front end to backend application with full telemetry working. And you'll see that remembering to connect the telemetry and also to provide and instrument correctly your application is a non-trivial task because again uh you have to do lot of things and let me just see sorry uh I am sharing only my screen right? Yes, indeed. Uh, let me change for a second. I'm sorry. Today I'm having issues managing my setup. Uh, stop in here layout and I want this one.
Okay.
And so I was saying that one of the things that you can say for example is that effect has built-in telemetry. And for some systems knowing why they failed is very important. So telemetry is one of the important features of effect that I would have liked to someone um when discussing about why to adopt effect. And there are also other things that I consider effect to solve that are missing in the bare plane um Typescript promise word. For example, we know that promise has lot of issues because again the promises for example uh represent something that is already running. So you cannot for example easily implement uh retries or implement interruption patterns over promises and effect make that really really really really easy because you just add a combinator and that's it. you specify how you can interrupt, how you can coordinate um your effects, your running things. And one thing that I always challenge people to ask is do you properly handle things like a board controller in your APIs or in your front end or in whatever? Uh well if you are not sure about the reply to that question well probably you'll be glad to hear that effect behind the scene handles for example interruption for you. You just need to specify how to compose interruption and interruption is automatically propagated and composed for you and that is this is again one thing that for example in this LLM era um where LLM tokens are very expensive.
For example, if you have an API that behind the scene invokes some LLM task, um maybe it's better to be conservative and be sure to properly interrupt the LLM task behind the scene and effect helps with that interruption. And again, u most people think, yeah, but I am using a serverless environment where the environment gets shut down immediately after the request u responds to the HTTP endpoint or things like that. And well uh sure that's true but that also means that you are basically for example dropping database connection as uh the API um completes and not properly cleaning up resources is something that um degrades your performance because again properly cleaning up for example a database connection is definitely better and in some cases even more performant than just letting the that connection drop to the deadpool.
And so another thing that I usually um say that is a fact has explicit resource management thanks to its primitives and that's really really really good from some use cases like that.
I hope that this gives you some hints on how to basically um present effect to um to your colleagues. Uh but I also would recommend you uh there is a presentation that I did uh at Fat Millan uh last year. I think maybe even before the last year uh that you can find here in the um effect YouTube channel um which is basically an introduction to effect and some of the values that uh effect presents. So um I recommend you to see this presentation and there is also a few other very very good presentation from Kit Langon explaining how effect is built behind the scene which is very useful also to understand how to solve effect.
So hope I un reply to your question.
I got a word question we're running into last week. I made my first logger a corized version of log fmt disco after discovering uh effect small uh number.
Is there any particular reason why log level loger option is of type log level and not severity. It seems like one of the log will never um my special types all or none.
Um we can look into that later uh because that I need to get more context about that part of the effect. But yeah, we could maybe look into that later on or always um is as if you don't have a if you don't have uh already um opened an issue for that we can show that. So let's also see in here.
Okay.
So another question, another question we got in here is for example, Baptist Arno asked, "Is there any reason why we'd want to use something like uh Drizzle effect over uh effect SQL?
Maybe let's pop over the chat in here.
So, we were asking about that. Let me zoom in maybe. Okay.
So, is there any particular reason why that's what we did before?
Uh is there any reason why we'd want to use something like drizzle effect over effect SQL something? Well, that's something we have actually discussed last time and basically the G is that you need to understand that the effect SQL family of packages are really just low-level drivers to perform queries over your database. uh whereas Drizzle is a full-blown ORM and again ORM and um database drivers have basically different purposes and also different limitations based on the approach. For example, uh potentially with an ORM, you can completely forgot about which is the database engine behind the scene and write only code in the ORM and that's beneficial if you want your application to be able to swap database provider and that's fine but again uh to do that RRM makes some assumptions for example they don't leverage very specific ific database optimizations because again they need to stay and to be kind of generic.
And so if you instead are looking to leverage some feature that's specific for your database probably instead you want to look into the direct effects SQL driver. And if you are using the beta um from drizzle effect uh they their drizzle uh effect uh for beta before uh is now baked on top of effects SQL. So that also explains you like the difference between the driver which stays on a lower level and the RM which stays on a higher level. And also usually yours have more complex features like for example uh diffing your database structure in order to reconcile it handle migrations in particular ways and etc etc etc whereas with effects SQL you don't find those feature um the main core idea is basically just to provide you a way to run queries over your database and then the only integration there is is the integration with schema because once you get back your data from your database, you then have to ensure that um the contract from the database and your code is actually satisfied because that's a boundary between your replication and the external word. So the time system cannot provide you guarantees over what's there and that's why um there is modules in effect like for example uh the SQL schema or whatever that allows you basically to run a query and then convert um the result into um an an a schema parsed object.
Uh I think that for example I should have in here for example you can see that I have in here in my code for example um some code that uh let me check is that in memory. Yes, that is in memory. So let me see if I have something else uh in here to show. Um maybe we can look into the effect codebase to show you few of the APIs that could be interesting for that. Let's say for example if we go affect small if you look for example for SQL schema let's go to the text examples for example uh you can see in here for example that maybe there is some example that's more real Third in here for example let's see in GS docs you can say that say it's a small adapter between effect schema and SQL statement to build function that accept the code request type by using my application code and code it before calling executed and then and decodes unknown driver rows into uh the result schema. So basically this is only doing the conversion between uh a schema you define and um the SQL query you perform.
So basically you provide it has methods like find all find an on empty um void which runs a request and those method really just um perform the query and then get back the raw result and then pass that into a schema which validates that the result is correct. Eventually the schema can also transform the results but that's not an that's only just um a layer around that.
So let's see if we have other things.
Max is Miami today I think. Uh I think so. If it's not today it's tomorrow.
Uh so when is it recommended to create wrapper errors like uh wrapper errors cause effect versus having defined as error one two or three. I'm doing both patterns and it's getting a bit messy.
Uh yes uh that is indeed something that um it's not immediate to decide. There is no real uh role of tomb. I would say that it's that or not because I would say that um this depends a lot on your domain because let me um maybe we can do an example over that in here with our uh ticket repo that we have in here. So we have this ticket repo uh which basically is um a service that has three methods. One create that creates a ticket, one list that lists the ticket in the system and one that closes uh a ticket. And there could be for example cases where um for now I may decide that uh yeah uh I could have a ticket repo error and that means that the ticket service has encountered an error uh while performing for example the create operation and so you would ask well what error could that be? Well, it could be an error for example due to the underlying SQL storage or it could be an error because um the schema encoding has failed or it could be an error because maybe there was a business invariant that uh this ticket repo is failing with. So how can I basically um decide when something should go uh into the uh error channel and something else should go in the cause of a wrapper error. One thing that I like to think about is let's say that I expose in here uh an SQL error.
Would that make sense? Yes. But if you think about it in here, we are defining a ticket repo service and explo exposing in here an SQL error. It's basically leaking how behind the scene this ticket repo is implemented. So let's say that for example in our system at some point maybe we have different stoages. we have a filebased storage and uh one that instead uh is based on SQL. Uh having SQL error in here probably it's not good because again you are leaking how your um method is implemented behind the scene. Whereas instead having in here a ticket repo error and having then class ticket repo error extends uh scheme oops dot um type error class with a cause being a schema oops schema dot defect and we will port schema.
Whereas having something like uh this where we have our ticket repo error that sounds better indeed because now you are basically hiding away uh between an behind an unknown that behind the scene uh an SQL error has happened.
And I would say that that's the distinction where um you should decide what to wrap and what not to wrap. For example, in here in our ticket not found, I would say it could fail with ticket on found and ticket repo error for example because it could be that there is an error behind the scene on how the repo is implemented. uh and um an error which is domain error of the ticket not found. And again um this is interesting only if you expect uh somewhere to have some way to recover from this error because if in your application there are no way to recover from this error. Well probably there is no uh need to just keep bubbling up that error. You can just fail with that effect in that case. So hope that that replies to your question that that is something that there is no rule of thumb. Uh it's black or white. Again I think it's something that depends on your business depends on if you expect that error to be handled or not. And um basically that helps you decide. And also one other last pattern I would mention as well is that if if you have errors you care about uh for example let's say that you wrap your um you you bubble this error into another service and you want to wrap this error.
Maybe if that service um is known to being baked by the ticket repo and you expect that also in the exposed contract, it's fine to use um instead of cause uh schema defect you can use reason and then you provide your error in here.
So that way you can use the effect catch reason family of APIs in order to uh not only recover in case of ticket repo error but you get also signal of which specific kind of error has happened in the year. So here it could be basically a schema union of error A and and error B.
Okay. Hope that uh that replied to your question.
So, uh why would you use GPT 5.4 over 5.5?
Uh because sometimes, uh the servers for 5.5 are so busy that uh they keep failing and so you fall back to 5.4 for for some times.
Uh I've been using the effect the TSO LSP. It works perfectly. Glad to hear that. I'm really really happy to happy to hear that.
And Ker following up with thanks. We'll check it out. Nice.
So it seems that the TSGO LSP works uh much better with V4 that uh V3. Does that sound correct? Uh it shouldn't be the case because the effects go LSP should work with both uh v4 and v3.
What's true is that thanks to the performance that we have in Go, we have some additional rules that are um in there in the TSGO version that specifically targets only on um effect um before because we have more performance now uh that we could port back to the old version. uh but it would be way way slow and it would make your your basically uh your editor compiler etc performance so worse that it's not worth it given the feature is the typeskit go by Microsoft um everything I am doing is mostly on that for the new features uh but I'll still backport whatever uh makes sense for v3 so if you encounter something that did don't work for v3 three, please open uh an issue because um either that's one of those things I mentioned before uh that uh I explicitly didn't added in the old version. Uh but usually that should not be the case. There should be almost feature party with effect three and effect v4.
So speed is saying I'm dealing with non effect code base right now. I'm dealing with an effect non effect cold base right now and um I would want to kill myself. Well uh please stay with us. Uh don't leave us.
But yeah I I feel once you once you adopt effect once you get into the effect way to do things it's really really really hard to get away from that.
Uh yeah, sure. I like to sell effect first by saying it is like the missing TypeScript library. It has nice stuff like daytime, duration, lash like helpers. Uh yes. Um that's also a valid point. Um one of the great things of effect is it's good ecosystem of data types that whole feel and behave in the same way uh which make one of the effect of one one of the effects of effect that is that usually it uh reduces a lot um your list of dependencies that you have in your application Um but yes, Arnos very clear. Thank you.
You're welcome.
So um effect is to plain JS what Rust is to PHP or is that too much of a stretch on the second comparison?
Well, probably I would say that saying that Rust to PHP. Yeah, but yeah. Um, I like to say that Typescript has been an improvement over JS and I would like to say that effect is an improvement over TS. also given um all of the all of the nice thing that effect provides type level for your agents and whatever that uh again um you don't get the same semantics in a plain u javascript or typescript codebase uh with the fact you just hover some types and you already get some be some business values some business meanings out of your objects um without basically investing too much in there.
Uh is effect v4 basically blocked on TSGO release? Uh once that drops effect uh v4 drops? Uh no. Um effect is effect as a library is not um tight to the typescript go release. Um so effect vss effect v4 is not basically blocked. It's still going on and we are right now in the phase of collecting beta feedbacks. And so if you have uh something that you are not happy with or something that you find missing in effect v4 compared to effect v3 um that's the moment to say yeah I'm missing this. I don't like how this is handled because the more time passes the more we are locking into some choices and that's why we are basically waiting a little for um moving on with the fact V4. Again we want V4 to be um a really stable release, a really long-term release. So that's also kind of why um we are being I would say a little bit conservative about moving on with that.
Uh uh thank you for explanation on the errors makes total sense. I'm happy that that reply to your question. So speaking about errors uh is there are a lot of them for handling error in HTTP client services.
uh I am working with on a cl a crawler indexer and I have multiple HTTP clients and probably need to differentiate uh each error. Well, uh you already probably give yourself an hint of what I would do in your own uh question. Uh because if you have uh different HTTP clients and every one of them is doing different jobs, basically it's hiding um an HTTP client uh but doing different stuff or having different configurations.
uh probably what you would need is either provide different services that basically just alias your HTTP client with different configurations uh or you should probably hide away your HTTP client entirely and create a service that performs your domain tasks and hides away the fact that behind the scene there is uh an HTTP client. Again, this is one of those use cases where probably in you can have that error with a reason field and the reason being the HTTP client error. Uh but probably if you don't want to match uh to mismatch the errors and you want to differentiate between which client raise which error in which phase probably it's good to wrap them and alias them behind uh some service. But again um unfortunately I cannot give much on this question. I would like to need probably a gist or something like that to understand more about what you are doing with those um HTTP clients in order to give you like maybe a practical example of how I would structure it. Uh that again it could also be different from how you land up but that's a suggestion.
uh in our v4 branch I can over effects and yield and it shows type correctly but it really does on our main v3 branch. So um if it's if that's the case uh I would ask you to please open uh an issue uh where you provide just um some snippets of code that type checks. uh is it it's still fine if you replace the actual implementation of function with just the declarations of the signatures and um that's really it because that would help me to uh understand what's going on regarding this feature.
Um can you elaborate? Yeah. uh if you're familiar with uh I want to make a typed client and I have to deal uh with schema errors of response errors uh output andor uh request parameters. It's a little hairy.
So yeah, in here probably you want to hide away the fact that uh you are using an HTTP client behind the scene because uh probably uh I'm not too familiar with a T proto but probably you can you could even write um something that uses behind the scene the structures you used by effect RPC to define your RPCs um if you want that type client. Uh but yeah, because when I call when you call HTP client response schema JSON, it can return an HTTP client error or your schema error and that's where uh you should probably map those into uh your domain error.
uh if I want to do property based testing on a fed code basis, how should I approach it?
So um to do propertybased uh testing uh what you can leverage is um using the effect schema which allows you to do property based generations of structures and you can use uh let me check let me bring it up on the screen in here we can go in a more.
Uh we have some um effect vital that uh this integration if I recall correctly also provides some utilities to perform tests with um property based I yes you can see that uh you can do with for example iteffect.prop prop. You can define uh schemas or you can that you can define yeah you can provide a fast check which could be also derived from an effect schema and then you can have your test implementation be out of that properties that you have uh defined before. So I'm not sure if that what you wanted to ask but hope that uh this helps.
So um following on the previous discussion, I have my HTTPA client that extends HTTP client and while internally it has sh of things, I also have static um my HTP like that that executes the request and wraps it with the correct error.
I'm not a big fan of having a service that extends another service because first um providing this service if that extends this one will also erase at type level the dependency of HTTP client and that's not true because at runtime instead you are not erasing And then again it is more what I usually um I prefer is composition over inheritance. So probably again having an entire HTTP client and adding features on top of them of that probably sounds like something where you need to split your service and have maybe your service provide only the additional function and then also provide um an accessor to the underlying HTTP client if you really want to uh access that behind the scene.
So um he's a guest. Uh oh, usually the URL we post in here um don't survive due to how due to how YouTube buns the URL. Uh so please uh post your G URL uh in our effect discord channel so that way we can see that you can see more of that in there.
Can you explain optics and why one should use them? Well, probably I'm not the best person person to answer that question.
Um, Julia is very good at explaining optics.
But maybe let's first finish uh this journey we have about this gu and the HTTP client and then maybe we can go back to that question. Uh let me see let me see. So um this seems that it is selfrunnable. So I can just combin it and we can maybe uh that was the name right and the other one uh was atypto and that one xrpc.ts Yes.
Okay. At proto xrpc.
Okay.
Ooh. Oh. Uh. Yeah, we have some errors because you we are on a older effect version, I think. Uh but we should be able to fix that pretty quickly. Okay.
Okay. Uh so let's see. Let's see what we have in here.
Check for hidden uni code I prompt injection in untrusted gs. Yes.
Yes indeed.
Uh so let's see. Uh so in here uh you have basically uh your uh codeex uh you have a date which is basically a branded string from what I understand and then we have handle which is again a branded string with a specific pattern and SID and so goes on.
Okay. So we have defined some patterns and then we have XRPC and XRPC defines first uh error response which is a schema class as an error and a message and then we have a response error which has an error and reason that's not of type schema I suppose is because of the HTTP client error and this parse error uh I would imagine is an error that wraps the parsing of either the params the output of the error there's the underlying schema and the client error and HTTP client response. Okay. And XRPC client error.
Okay. And then you have your XRPC client which basically is an XRPC client contact service. Okay. as a service that then constructs back some preconfigured HTTP client with some mapping some retries.
Then you have a layer client.
Then you have a make query that basically takes in uh the ID that we have defined before some codec that converts uh given params to an URL and output into JSON.
Then we have some annotations. I don't not clear to me what this annotation do but again probably it's because I'm not too familiar with the syntax also please please please adopt the fact that Jen please I I know that some people like the flat style but yeah in here probably an affect the gen would help a lot. Um so basically we start with the params we encode them and that also maybe connects to also one of the reason why it gets fiddly for you to handle the errors. Uh basically here you are encoding the params and then you map that error into a parser for the params and then you create a get request. Uh you use that over overexecute.
You catch the HTTP client error with fail error.
Catch tag.
Uh this HTTP client error status code error.
Uh I think that is basically a catch reason.
Uh, HTTP parse error. What was it? Sorry. Uh, HTTP client error status code error. So, that could be an HTTP client HTTP client error status code error. Yeah, see this helps because you you were before just refailing the error just to satisfy the pipe and with catch reason you can rewrite the same and wrapping just the reason and then you get the reason uh you start from the reason also yeah um I'm sorry But I mean why would you know even in the first place uh reason do uh what was it?
Uh reason response.
Okay, you're basically starting with this, right?
Or which could be even this bro has OCD. I'm sorry. Yeah, that that's indeed the case.
Uh I have OCD indeed. Yeah, when I see things like that, I have to change the style. Yeah. Uh, map error, then you map this error into a parse error. Again, you annotate that and then you flat map that into a response error. I mean the the issue in here uh not the issue the things that I would improve in here probably it's not even much about the error shape uh it's more like the pipe handling probably yeah because again uh I think that this could be easier to manage either by using some effect generators which could give you a Okay, with all of these flat map top annotate logs uh map map error map error not sorry map yeah you could probably get something but overall I don't see many issues about the way the errors are structured yeah probably I would um probably I would just change that because the error structure Uh, it's not bad. I would probably give a better name to parse error because it's not properly a parse error and it has the same um type of error that's embedded inside of a schema error.
Uh, and could be maybe like misunderstood for that. But yeah, I would say that that's not too many an issue with uh your error structure. is more probably an issue on how uh I would say that you are making it more uh complicated for you by writing that in a pipe style instead of an effect journ I would say. Uh but again that's my that's my style that's not probably the issue.
I'm not sure if this helps but there are probably also some things like catch reason that we have seen before that uh could also be used in order to improve uh the readability and how these um basically flows. Um for example in here you also have top top error and I think there is um top there is like both you can match probably instead of tapping and that's it. Yeah.
Or you can even say something like uh on exit and then based on the exit say if the query has succeeded or if it has failed or interrupted or whatever.
But yeah, they just want to bill you to pay per yield generators. Yes. Um we will launch soon our uh paper yield. Um so yeah please yield as much as you can. So once we go on a paper yield plan uh we will make a lot of yield.
Yes that's indeed the case.
Uh hey Matthew what did we miss? Uh well we were discussing few things we were going on. uh an example and then I would say that this error structure again is probably fine uh probably it's getting hard to do because again you are probably handling these as a single flow and the thing is that unfortunately reality is not a single flow. uh even effect itself has a a split of binary something goes well something goes wrong and then in this case for example you have attempts of recovery or things that should be done on the error case so probably all of these is not properly expressing all of those things that are happening behind the scene I'm just trying to save a couple of bucks yeah that's indeed the case Um I'm sorry that probably you expected like more a golden solution but I would say that the infrastructure is is fine.
I mean from what I grasp of the domain of the problem it is fine. Again, probably I would give uh more uh meaningful names to the error, but that's my personal taste because again response error uh maybe it's more an XRPC response error or something like that just to understand better uh what kind of response error or parse error we are dealing with. Uh but the flow of the code is fine. it's written in pipe style which um for flows like that I don't like much uh but that's my personal taste it's not something wrong with uh the code I would say uh one there was a one tweet recently uh that uh I think it was Dylan Murai who did it um let me check it uh that basically said something uh about deep style of writing your effect chance.
There it is. Let me show it on screen.
Uh this exactly matches uh what the style that usually I use as well. Uh I have effect gen or effect.fn FN for if that's the case and then I I have first my business logic and then I leave compositions patterns in the pipe that's after or the arguments for uh the effect of fn. So for example going back to um your code u I see initially that uh you have a long flow uh that is actually encoding different steps. So probably the first thing I would like split those different steps maybe in something smaller and then because again this is just encoding the params and failing with an error. So this could be something like um a const itself that is performing just this task and then you can have basically an effect gen that invokes that part of the code that you have extracted away and then uh at the end you pipe and you had things like for example the spans the scoped uh you annotate the logs and probably you also add things like um this matching on the error uh to print if the query succeeded or failed.
It was Dylan. Yeah, it was Dylan. Yeah, I really enjoyed that style. Um, it was about that, but that's exactly one of the way I think about them. Uh usually I have business logic and then I have things that add on top of the business logic like telemetry mapping errors into specific kind of errors for the entire workflow. Uh or things like as you have in here logging uh success or failure things like that.
Uh let me also uh check Um, let me also check uh if we don't have any questions on the Discord channel. We don't right now. Okay. So, going back to um our chat in here.
Uh that makes sense. Uh pipe pipe has 5% performance gain. No. Uh well, uh that's not actually the case. Um because if you have a long enough pipe with combinators that just map or uh for example you had in here uh a map in here or you had a flat map or things like that. uh you are basically uh through those operations you are emulating let's say um a JavaScript scope and that means that every time you do a flat map uh you are uh basically performing new instructions over the uh effect runtime. Uh whereas when you do when you do something like and then you const a equals uh one and then you say b equals yield star let's say that we have this very simple program whenever what is that you are doing is uh for those operations like mapping and fat mapping we are basically leveraging um the generators and the JavaScript native scopes and turns out that um it's not actually the generators that are slow uh generators are nice are good uh the thing that is slow is allocating generators um So the thing is that probably allocating lot doing something like this doing something like this um is probably bad because every time you invoke this function you are allocating a new generator and that's why effect has uh effect. Fn so with effect. FN you basically have the same program but this time your generator is allocated only once when your function is defined.
So basically that way you get a way that instead of paying the cost for allocating the generator each time uh you basically allocate the generator only uh every time you define uh a function which should ideally be only once.
Um, but for some reason I'm scared of helpers that only get used once. Uh, but it would probably make it cleaner.
That's my point. Um, you should not be too scared of that because again, um, having that three instruction in a row in a flow that's made up of like 40 operators uh, one after the other. uh by just looking at this and scrolling up up and down um it's really hard to understand uh what's going on. uh whereas if you had instead something like let's say uh we had pipe and we say uh convert barams bars effect flat map perform request clean up logs or maybe print accent.
I would say that this reads way better than these um because you don't have to read the entire flow to grasp what's going on. um you first understand the business logic which is that function basically is converting parameters performing a request and then doing something when it exits and then if you're interested about the actual implementation of something like convert params that's fine you jump into the definition of that and you're fine.
Um, let me drink a little um, and see you to update dependencies in packages.json JSON uh does not pick up certain changes to affect packages um 49 to 71. Yeah, that's uh a known issue that packages package managers have uh with uh beta releases um in the way that the beta number is structured.
Unfortunately, there isn't much we can do about that. Um it's actually one issue on the side of the package managers.
Um, I I also don't like naming things, so Pipe helps me not to have to do that as much. Uh, yeah. Um, naming things is hard. But if you gave, you know what's even better? Uh, being able to just hover something and see the types. And if you have things like uh convert params and you are not properly sure uh if the name is conveying what it's doing one thing or effect you can over its type and the type can tell you that this succeeds with the type can fail with the schema error type conversion error etc. And so um you are not just relying on the name you are also relying on the types that the hover can provide.
I've sent you 40 line of code for judging against affected zen versus uh pipe discussion. Let's see uh talks on code below. Um let's see let's share it in here.
talks on the code below regarding effect gen versus spike discussion. The idea is to have a single line of code that reads uh something from the DB and the code sit with the schema without needing intermediate variables.
So in here uh I can copy this into a file maybe just to see it bigger in my editor. Um, yep.
Okay. Uh, we need we need effect. Uh, we need uh option I've seen and schema layer layer and that's it. Right. The other one I could not have. Okay.
Okay.
Um, so regarding this, you have a make, which I think it's a make for a layer for constructing a layer in effectful way, right? Uh, is that correct? Let me just pop down the chart.
And then you have these um that is attainable API so that's fine if option is known binding then you do that error not find not found error otherwise um you return the bending well uh to be honest Um this is one of those edge cases where um from how it's written in ER this could be really just um could be also be written as a single function uh even without having flat map or whatever because there is actually no need of that uh because um this is already an effect which returns an effect that has uh our database error uh in case this fail and then you do undefined.
See in here you do what's what's not clicking for me is that in here you are basically taking the the result if I get correctly and then you match the result if it's undefined you succeed with none and if it's defined then um you attempt to decode. Okay. And so uh I would say that probably succeeding with none in here uh is not necessary because you are already flat mapping. So you can return uh this error in here directly directly and that gets away of that.
And if uh you have this flat map you in case nothing is find uh then you fail with your error and in case something is fine then you don't have to do a sum anymore you can just uh decode and that's it. So that means that there is no bending anymore and so there is no need of doing that anymore. And so that means that probably uh given this function only has one yield um you can basically have this as a single pipeline.
That that would be my my point.
uh you are I would say that probably you are overwrapping things uh because again you had something that was undefined and instead of failing first because you got something undefined you decided to go with none for them but then that none wasn't used for anything there it would would have made sense if you had for example let's say that uh you perform this query and then you get back an option with either value or nothing and then maybe you get or else that or else you succeed with other thing. Uh that could have been one reason to have the option because maybe then you compose with another option. But given you were using the option just to decide if you wanted to throw the error or not probably I would not say that I would not um I would not use option. And then uh again um given you are using a fendant traced so that means that you are not capturing um the um tracing at cold side of the telemetry that effect. Fn instead gives you um then you can again remove this entire generator uh because again it's yielding only only one thing. So you can just have uh the bear the bear account ID function that takes that and goes there probably would be would be my my guess. And uh one last thing but that's probably um that's probably more something uh I prefer stylistically. Uh so it's not something you should do um unless you you you're okay with that is that for example um if you look at this um you are basically mapping the error in here but then this error is not uh recatched or handled in any way after. So probably uh we could leave this is more a style of how I like to write the code. You could probably just leave the error be bubbled up and then map uh the error in here. But then one would say yes but now this error would be wrapped as well and that's why when probably I would use instead some catch tag of my potential error that is being raised by this let's say error and probably um and probably you could uh remap that in here so that you can basically uh do also things like this fails with uh a schema error. So you can say in also instead of catch tag you can say catch tags and you can say when you have a query error you convert that into that and when you have a schema error you just say effect fat or die and that's it. So that way I have basically moved uh almost at the end um the handling of the error. But again that's more like how I prefer to write the style. I prefer to handle the errors as late as possible uh rather than as soon as possible. And handling the errors also means mapping the errors because mapping the errors is effectively one way of handling the errors. you are taking an error and converting into another one. And that's one way I would um I I would do that.
Yes.
Uh then that's so clean. Yeah. Um it's not easy. Uh but once you get to grasp it, it it starts clicking how you can simplify that. Um the idea to have effect map error before effect up is to ensure uh if anything changes on drizzle side the error will be still be code as database error. Uh well um you could do the same uh because for example um if you say that your um you're in here you're just interested in our uh fire block firebox account error and your um other error which is a schema error. You can also use uh the or else parameter that's in here and this or else parameter in here basically gets applied to any other type of errors and so you are basically saying yeah when a schema error happens uh I want to or die and for every uh every other error um I wrap that into um a cause and probably things like uh our Fireblocks uh account uh error. I want to uh keep that uh as is with an identity. Again, that's a style.
That's not the correct. There is not a correct and a not correct way to do that. But um I like this because I like um basically to see the endling at the end or at or as late as possible um as I would do that. But I get that some someone would say, "Wait, wait, what's happening in here?" Again, that's a style. Um, even the solution with the map error in before is fine. Uh, it's just something that I like to have the running link at the end.
Uh, let me see if we have something else on there. No. So, I seen before there was a question. What do you think of wide events in logging and tracibility?
Uh well uh they have sometime sense and sometimes probably they are an overkill because again logging too much and logging nothing probably have the same issues because when you have too much data then finding things that happened uh becomes difficult. So it kind of becomes the same that um if you don't had that data at first but yeah uh if you have a system that then collects your log and let you uh filter your logs like you store the logs in loi and then with graphana you query them um that probably makes sense.
Uh very interesting style. Thanks. Uh I hope that this was interesting for you.
Again, that's a style. That's not um that's not something that um you should do that and if you don't do that, that's not correct speaking. Um but it's a style that I like um to try to put things and the handling as late as possible.
And again, one thing that I really like to do is uh this explicit uh type of uh schema error and then saying affect die.
And that's the And that's fine.
Uh, Matia the goat. Yeah, I'm a goat.
Uh, time to spend the next two days on refactors. Indeed. Indeed.
Um, there is this meme uh meme uh there is this meme I I really like. Uh, opening a new window.
Yeah, this meme I really like. I have big plans for this code. Please don't worry factors. Big plans.
Yeah, that is exactly how I read your your comment.
Okay, let me get back to the chat.
Uh so effect subtyping is back. Uh yeah uh effect subtiming is subtyping is back. Um I think we already have discussed that uh in um in a recent stream if I recall correctly. Um but basically um we removed the yieldability and we basically had um back the subtyping but this time the subtyping is more strict. Uh we are now not just having subtyping just because it's fancy to have. Um we now have uh subtyping only where it actually makes sense and only where there is um a clear meaning of uh what that type uh would mean. For example, um if you check um for example, if you check things like um the fibers, for example, and we go into the fiber definition, the fiber is not an effect subtype.
It's not an effect subtype because again um in in effect V3 you could have yielded uh fibers but it's not clear what's the meaning of yielding a fiber um are you forking that are you sorry are you joining that are you awaiting that what's the meaning when you for example yield a fiber and that does not make a lot of sense so that's why in V4 fiber is no more a subtype of an effect. But for example, um if we look into uh give me a second so I could open uh the effect source code just to show you uh in here so we can show all the types that have survived the subtyping.
in here.
Uh, yep.
Okay. Uh if we zoom in uh zoom in zoom in zoom in zoom in zoom in zoom in zoom in.
Okay. And if we check um extends effect dot for example. You can see that exit uh still extends and subtypes uh effect.
Uh we also have still things like uh where it is where it is where it is affectable prototype find the references.
We still have things like for example uh a child process effect subtypes effect uh because then when you have uh things like a child process description uh yielding that describes basically as spawning that's a process or in things like effective workflows.
um yielding the effect uh of one activity um basically means executing that activity inside of uh workflow definition. So evaluate basically runs I'm sorry runs the execution or things like for example um uh yielding an effect context um mean an effect context service tag or means basically just attempting to get the value of that service. Uh so things that where it makes clear sense uh are still effect subtypes and um we opted out uh to yieldability instead. H because um it was not great for things like workflows and other primitives where you still had to write a lot of dot as effect in order to convert whatever you had into an effect. And instead we did also a pass over the APIs to ensure that there are um no APIs that implicitly uh without you doing that explicitly flatten things. So that um there is no risk that um weird ch error channel or weird things happen without you um explicitly call things like flatten etc. I should have that as a poster. Yeah, I I really like that meme.
After the 24-hour cluster stream, I'll bet I'll spend a month refactoring the code. Well, again, we are down to I would say 14 hour stream, right? Uh are we discounting the hours as um affect office hours passes, right? That's how it works, right?
Uh is there a clip? Um I don't recall if there's a clip. Uh I don't actually recall if it has been discussed. I think so. Uh but lately my memory is um joking with me. So sometimes I recall things that didn't happen. So, um I'll double check that after the stream ends and post over the office hour channel uh the link if I call if I find that again.
Okay.
So, uh do we have other uh is there a comprehensive list of which types are subtypes of effect? Uh I don't think uh right now uh because again uh we are um moving with the beta so things change but I don't think that we have one. Uh the way I usually look for that again um is just by watching everything that extends um the effectable prototype or uh the effectable class. Um those are the two primitives that basically uh are used intern even internally as you can see uh to define new uh effect subtypes and this gives you a good slice of the types that subtype effect.
Okay. So do we have other questions right now?
Let me see. Let me see.
Makes sense. I'll try updating soon.
Yeah. Hope that the update goes well.
And I think we were discussing today that probably we will at some point also make one update uh of what happened between the the beta question the beta releases. Um but yeah oh I had the optic question but Mash sorry uh I forgot about that question.
Uh so uh let me uh check it again.
It's here right optic.
Can you explain optics and why one should use them? Well, I would say that if you going to uh let me open up If you go into the effect small repository and you go into packages effect optic.md, it gives you um basically um packages effect optic.md.
It gives you an overall of what an optic is and what's the purpose of an an optic is and basically optic let you focus on parts of immutable data structure to read and update them in a safe composable ways.
So basically with optics you are basically creating lenses that's why it's calls optic. Uh there are other data types other than the lens but the lens is one of them. Uh that allows you given a full data structure to focus on a specific field and you can then read that specific field from the entire data structure or construct a function that given uh the optic the entire data structure and a new value for that specific optic lens. for example, it creates a new um version of the full data structure with that specific field uh updated.
Um so for example uh let me show if we have in here. Yeah, you can see that in here for example, we define first a structure uh S which has only a key A of type number and then you create an optic identity that starts from S and then you focus on the K E and then this underscore A uh is basically just a function that when called with a full structure with uh A1 then returns you the value of just that val that the field and then it also gives gives you uh things like for example replace and modify that as I said before allows you to change the value uh at that specific lens at that specific path and create back a new copy of the entire immutable data structure uh with that uh updated and this seems an overkill for probably just one field but that becomes comes more useful when you have things like these when you have structure that are very deeply nested very particular where you can have things like I want to get the street name yeah you start from an employee you get its company their address the street and the name and then um if you want for example to modify uh the street name and be sure that the street name is all uh capitalized well uh you can just say take your optic and then say modify the function that will transform your string. It will string. capitalize it and then uh you create you call that from an initial structure and then you will back get back the updated struct the updated um data. For example, you can see here that initially we had high street with the H being lower case and then after calling that now it is upper case upper case and then monocults is back. Yes. uh monocults was uh optics for uh FPTS and now in effect there is built-in optics and uh again the basic usage is what you have seen uh you can create with key and then um you can for example use if a field is always present use key uh if the field is present but you you probably uh have cases where when you want to drop that. If it's undefined, then you use optional key. Uh if you have a field that's an a union of different cases targeted by a tag, you could use tag to address a specific member of those ones. Or if you want to address a specific index of an array, you use at or if you want to uh basically target all of them, uh you use a combination of them. And I and there are also like uh other things like for example let's say that you want to create optics that only get groups of things or omit some fields where you can see in here that you can have function for those as well. Um an optional key in a structure double that's that was one of the things I wanted to show you. If you have a type S which has a field that's optional um in here it's optional it's a number or undefined you can first create an op a key that gets that and that's undefi number of are undefined and you can see that uh if you call get result with a1 you get a success and if we call that with something that's not that key defined we get undefined undefined and then Um if we use instead optional key, we can instead drop the or undefined we had before in that field. And now uh the optics library will treat the undefined as uh a way to say uh that field uh should not be there. And you can see that if we uh replace that field with undefined, it automatically gets erased from the object. And instead if we provide a value uh that uh field is set to the value we have provided and then we have we we we were one more example but again um I would recommend um looking into this document. Uh the only last thing that I would uh point out to is the fact that um you can also derive optics automatically from schemas. So if you have a schema that defines for example strct with some fields and whatever then you can uh basically automatically um convert that schema to um an ISO and then get keys for that but also um you can do that from class schema and whatever. And the thing is that you can focuses on key but then uh the great thing is that um you can see here that uh what we are building is an immutable person basically a class a schema of that class that is a person and we want to uh replace the name and if you if you do that with a regular JavaScript spread for example uh what you what you get back probably it's not the person or it's like uh not correct. Uh and the magic behind these schema to ISO implementation is that you basically replaces the value and then it constructs back the schema the person structure. So that way it it is a proper person structure with uh that uh what is that underscore name pattern is that recommended? It is just a naming convention um that Julio I think adopted and it's just to point out that um this is a lens that points to the name field but that's not something you should uh you must have let's say and the last thing I want to do is that also um the optics um that effect schema has is integrated with um in produced from IMER. Um if we recall correctly the last stream where we uh have uh spoken about fold kit uh for example uh we mentioned that fkit um used an album style architecture and that means that your model needs to update in an immutable way taking the old model and create a new model and uh immer is a way to basically instead of spreading all the way or using lenses you basically call a function called produce. You start with um uh a state and then you get a draft. You are free to modify and line the things imperatively uh inside of the draft function and that has to be synchronous and then it returns back uh a new copy of said state uh object that has that value modified.
So basically you write as if as if the object was mutable but behind the scene it is just recording the changes you are doing and then creating a new object uh with the same um changes and then yeah declarative version manual angling of optional data. You can see in you can call produce and it works and that's really it. So I I I know this is a very very very very very very very fast um look through what optics are uh but hope that this explains uh the overall idea uh of the optic. Basically the idea of the optic is again to have uh a compositional data structure that helps you focusing on part of an immutable data structure. I would say like that probably not the best correct definition again Julia would be better at explaining that um but that's the basic gist I would say um it's something that given a an imutal level that a structure allows you to focus on particular part of that structure and perform operations over that part of the structure by creating new copies of the original uh immutable data structure.
Okay.
So, do we have other questions? Let's see.
Let's see. Let's see. Let's see.
Let's see. Let's see. Let's see.
I don't think we have other ones.
Uh yes, I can close this one. I don't need anymore.
And I think that we also have reached a good amount of time.
So it has been as always a pleasure being with you. Hope that everyone will continue this amazing week. Hope that everything goes well. Hope hope that no one breaks something in production because that's not good.
But that's fun. What happens?
So, thank you everyone for joining up and as always we will be here again next week, next Wednesday or next Wedness Fact Day as it has been named few weeks ago. And well, that's really it. So, thanks again for joining and see you next time. Bye everyone.
Related Videos
Agentforce NOW AMA: Build with React and Salesforce Multi-Framework
SalesforceDevs
490 views•2026-05-28
How agent o11y differs from traditional o11y — Phil Hetzel, Braintrust
aiDotEngineer
450 views•2026-05-28
WEB TECHNOLOGIES UNIT-2 | Degree 4th sem BCOM Computers web technologies unit-2 full explanation💯✅
LearnwithSahera
1K views•2026-05-29
More tests are always better? How to use AI to identify tests that bring little value
Alliance4Qualification
335 views•2026-05-29
Search Algorithms Explained in 60 Seconds! 🤖💨
samarthtuliofficial
218 views•2026-06-01
People of Game of Thrones using JavaScript DOM
AltCampus
296 views•2026-05-30
Introduction to Problem Solving Part - 1 | Lecture 1 | Intermediate DSA
ascensionix
107 views•2026-05-29
🚀 BCS613C Compiler Design | Module 1 to 5 Schema Evaluation 🔥 | VTU 6th Sem 💯 #VTU #bcs613c #exam
Pranavaa-y4y
104 views•2026-06-02











