Function piping and composition are concepts from functional programming that of course are possible in JavaScript -as it's a multi-paradigm progra...
Some comments have been hidden by the post's author - find out more
For further actions, you may consider blocking this person and/or reporting abuse
I'd like to point out that the pipeAsync and composeAsync functions are examples of monadic composition! π
Indeed they are! ππΌπ
Thanks for sharing such a neat concept. Also, +1 on using JSDoc (Get the TS code outta my face. Kidding, keep it.).
π
To be fair in this situation it can, effectively, be
any
πThe return type would be the return type of the last function called and the type to pass to the next function would be the output type of the one before, but I honestly don't know how to express that in the TS type system nor if its possible. π€―
These situations always keep me thinking about why I am using TS in the first place. You will end up spending so much time figuring out the types in these tricky situations, which is NOT a business problem to work on in the first place. That's why I would love to revert back to JS, anytime.
Because the absence of types (nor
TS
norJSDoc+TS Pragma
) leads sooner or later to non-expected paths that can break the app in runtime, which is a business problem that will rain as sh*t over the dev team (Imagine you spent 200k on a marketing campaign and the app crashes avoiding the conversion that could eventually amortize the costs plus benefits).Are the types necessary in every single App? No, they aren't.
Still it's recommended to have them in most apps. On the other hand, JSDoc + TS Pragma (remember that JSDoc alone does nothing but printing an informative text, you need TS Pragma to get type checks on dev time) is better than nothing, but TS has much more features than that.
Yep. Although the absence of types may not be considered a major problem by some, me included, I believe that not following best practices is what ultimately causes more issues in web development. By adhering to established conventions and standards, we can avoid many of the potential problems that can occur without these guidelines. In addition, following best practices often leads to code that is easier to read and understand, which can save time and frustration for all parties involved.
But, the thing is that major business issues, even though I don't have data but from what I have experienced, are not necessarily caused by the absence of types. I think there is a correlation between the two. But, the relation is not causation. The absence of types doesn't necessarily lead to rain as sh*t over the dev team. Know what I am saying?
Agree.
Of course not, the main issue is not having tests.
Key in the discussion here being that coding in
TypeScript
is faster thanvanilla JS + JSDoc + TS Pragma
, you may never seen it this way but look:As well as more reliable.
To get a similar reliability with JSDoc you need to ensure JSDoc is added and maintained through automatisms in the linter and run this step in the PR's pipeline, at least (i.e. ESLint plugin JSDoc) and it takes more to configure than what it takes to configure TS most of the time.
Keep in mind that using JSDoc and TSPragma you are just using one little piece of TS, which is about type definition and type reports (and it doesn't even cover it entirely).
If you just need those features, then add TS and just use those features π
Do you dislike interfaces? Fine, don't use them, if you are working in FP instead OOP, interfaces doesn't even make sense (in FP all functions are interfaces).
It is not mandatory to use everything from TS so don't stress it so hard π
π―
Great article! Love the fact that you include the
async
versions.Glad to see people interested in this topic!
I have a YT video on this same topic: youtube.com/watch?v=q1aNVIq3K7c
where I show some real world examples. Feedback is very appreciated!
I just knew pipe and now I know it differs to compose by just order of function execution! Thanks
That's not always true, though.
In Elm, for example, pipe
|>
and composition>>
have the same order of execution, the difference is that pipe is imediately executed while composition returns a new function:Note: Everything after
--
is a comment in ElmNot only in Elm, but pipe in fp-ts also works this way:
That's why the post has the tag #javascript π, either way love the insight! I haven't coded in Elm in ages, actually a good one, absolutely love the no runtime errors π€©
It's sad that it got relatively few support...
Yes, but even in Javascript this concept can be different as you can see in fp-tsβ pipe.
I love coding in Elm! It is my first option when creating a Frontend.
From what I see, it seems some companies are adopting it, so, it seems itβs growing
I picked the mathematical explanation for function composition:
in which case, this will fit in the description:
The implementation details or nuances in Elm (or any other) is a different matter of discussion π
BTW glad to hear Elm it's getting a bit more love!
You are right.
But the point of my comment is
pipe
.This is the one that have different implementations.
I just highlighted that the affirmation βpipe is the same as composition but reversedβ is not always true
oh! understood now π my bad
Anytime π
WoW this is so cool!
In the last example, I think the
pipe
frompipe(square, sum)([3, 5]);
should becompose
.Hi Gohomewho, thanks for pointing it out! I'm fixing it right now π
IMHO, the "ugly way" is a lot more intuitive and easier to read. Not that I don't appreciate the work you've done or the insight I gained from reading your article. βπ»
It's your opinion and when you use it in your projects, it will be your code, so use the style you prefer or feel more comfortable with, it's totally OK! π
Edit: I wrote the post in different days (one bit at a time) and just realized I had been using different wording for the references on those functions
So for this one:
we could save few keyboard clicks by coding it like this:
Just like this in the last one:
Which is probably more... understandable?
Let me know, if it helps I can update the post! π
Nice Joel, thanks π
Thank you for reading John! π
Can someone give a few examples of where this might be useful in the real world? :)
Sure!
If you apply good practices and split the code in single-responsibility functions you'll end up chaining quite a few of them.
In OOP you'll do something like:
Whereas in functional programming it will look something like:
Which is objectively better than
Specially as the chain grows and for readability: you can actually read them from left to right in comma separated names, plus having just one initial arg usually helps to avoid side-effects.
So it's not a niche concept but a generic one, a nice to have (and use).
That's a bit of a silly example but it may work just to showcase, also you can find another example in the post π
It's quite interesting things, thanks for writing about it
Π‘ongratulations π₯³! Your article hit the top posts for the week - dev.to/fruntend/top-10-posts-for-f...
Keep it up π
good article
Thank you Winsay π
Great Post!
Thank you Anna! π
Very interesting, I also learned about curried functions. Thanks for sharing!
I like thisπ₯
yeah,
just need one package, caolan.github.io/async/v3/docs.htm...
In the magical world of JS,If one package cannot be solved, find another package
Why to add a dependency to the project for something that takes less than 5 LoC?
I believe the power of the community is greater than the individual And different developers have different abilities
But is the individual the one that would need to solve dependency compatibility issues, so choose wisely which ones are you going to import, because the less you add the more ease you'll be granted with during the maintenance of the project and further developments.
Yes, in the end, individuals are always dealing with these problems.
Nice explanation and code examples. I still think you should ditch jsdoc though π that said... Array reducers are the only time I dislike typescript... It always produces a type collision between the initial value for the reducer and the current value, so you always have to give the initial value an explicit type, instead of relying on type inference, which I prefer, because having to make changes in explicit typing (when they aren't for data models) sucks imho. Not sure if it would be technically possible for typescript to infer the type from the return value of the reducer function though... Probably not.
Hahaha I prefer TS unless it's a quick script tbh, but IRL there are so many projects without TS that I feel like necessary to spread a bit of JSDoc (it makes it a lot easier to migrate JS to TS).
Type inference would be possible I guess but when you have functions that return different types then it will be a mess, I can imagine something like:
userAge is a number, then you calc the amount of years he needs to work before he can retire, which can also be a number, everything OK here, then you cast this number as string inside the email body so the return type is not a number anymore but a string, and so on and so forth.
Hence I assume that even if TS tried, most of the time it could be wrong idk π
1