re: Practical Ways to Write Better JavaScript VIEW POST

FULL DISCUSSION
 

Great read! While I do agree with you in 90% of what you said, you've explained everything quite clear!
My pet peeve though is asking JS developers to switch to TypeScript. Don't you think TS tries to force an OOP paradigm into JS, which is not necessarily OOP?
Wouldn't you agree that instead of forcing people out of JS's paradigm so they can write better code, it would be better to get them to actually understand JS's paradigm instead?
Just asking to spark conversation, I would love your opinion on it, I was never able to get on board TS or CoffeeScript back then either.

 

It has nothing to OOP. Type systems exists also in functional languages like Haskell Elm or OCaml. I can only agree that type definitions looks similar to these in OOP languages. But it doesn't mean you need to do OOP, even such functional lib like Ramda has type definitions.

 

Agreed, If I where to say that classes (singletons) could be used in a functional programming, I would be branded a Heretic, but a class is just a data structure, it's so tied to the OOP identity, that is all. FP in my eyes, is not about functions at all, it's about expressions over statements and immutability more than anything. Optional typing is a language feature too and nothing to do with FP or OOP. I wish FP and OOP would just get a room and make a little FPOOP 🤯

If I were to say that classes could be used in functional programming, I would be branded a heretic

No you wouldn’t, OOP and FP are orthogonal and a language can exist as both. F# is a good example of this, it has classes and even inheritance but I don’t think anyone would argue that it isn’t a functional language. FP isn’t even about immutability, OCaml, for example, has mutability (and also OO-like objects).

I wish FP and OOP would get a room

The term you’re looking for is object-functional programming; although it is slightly fringe.

😆 the more you know, thanks Andy I have learned something today.

It's an incredibly common misconception; I thought the two were incompatible for years too.

It does get discussed often as if the two things where oil and water. F# is one of the mid sized language I am still to research, but you have given me a reason.

I think this is mostly a consequence of two things:

1) Almost universally, you learn only OOP in school / bootcamps / self-learning. You have to actively search out education on FP, which means that when you inevitably do come across it after years of writing OOP it can seem so alien as to be completely incompatible with what you know.

2) When most people think of FP they think of Haskell which:

  • Is statically typed
  • Is immutable
  • Doesn't have objects at all

Haskell being the poster child of FP has lead to a somewhat inaccurate representation of the field. Many people assume all FP is Pure (immutability, no side effects, referential transparency), when the reality is many functional languages describe themselves as pragmatic; allowing for controlled mutability, side effects, etc...

To bring this discussion back round to the original conversation. Modern javascript is getting very functional: we've always had first-class functions, but now with methods like map, reduce, and arrow functions we can write our code in a very functional style.

Typescript, on the other hand undoubtedly favours an OO style. You can still write functional code, but it's a bit more hassle and you'll often find yourself reaching for features found in other typed functional languages that just don't exist in ts / js.

In Elm, for example, there is a Result type that models a computation that can fail. It looks like this:

type Result e a
  = Ok a
  | Err e

it looks like you can achieve this in typescript all the same:

type Result<E, A>
  = Ok<A>
  | Err<E>

But if you know ts you know that this is invalid. In the Elm version Ok and Err are constructors for the type Result. In typescript, Ok and Err are types themselves, and so we need to go ahead and actually define them.

I could continue, but this reply is getting too long and I'm sure you (and others) get my point. Even fully typing a curried function becomes a jumbled mess:

const add = (a: number): ((b: number) => number) => (b: number): number => a + b

My opinion stems for a video of functional c++ of all things. Anyway take this reply and make a post this is interesting!

 

Recent TS release notes have admitted the oop paradime and are looking at changing the docs to fit FP which typescript is certainly capable of doing. It's just poor marketing.

 

I agree. Typescript is unnecessary and it speaks more to the inexperience of the developer using javascript than enforcing good practice. I am a huge proponent of TDD (Test Driven Development), which innately forces the developer to gain a more in depth understanding of javascript and functional programming.

 

I have been programming for decades and most of that time has been in 100% in JavaScript. I prefer TypeScript and have used it exclusively on the backend and front end for 3 years now.

speaks more to the inexperience of the developer

So if I am an experienced developer and tech lead... maybe... just maybe there is a reason why I’ve chosen TypeScript. Use the best tool for the job.

Additionally, I only write in a functional style. TypeScript has never impaired my ability to write FP. Map reduce for life. Btw, ImmutableJS and Ramda have great type definitions. And as someone above said: Haskell has types. So... what’s your response to that?

The biggest problem of typescript that it is not sound. It forces you to always write complex type calculations. For FP it is very essential. When I used reasonml I was focused on writing the code. Flow also fits much better because of the same reason. Try to add types to a reduce function or to transducers. Typescript is not strict even in the strictest mode. Type casting to unknown to whatever or adding exclamation marks to the code. React works much better with Flow than with typescript. After switching to typescript I feel more like types developer.

 

For me you can't tell it's better way to write JavScript code and tell people to use TypeScript.
You're not talking about JavaScript anymore.
as

deleteman123 image


says it would be better to get them to actually understand JS's paradigm instead.
 

You don't have to write object oriented TypeScript. Also, JS is just as much OOP as TS is.

Wouldn't you agree that instead of forcing people out of JS's paradigm so they can write better code, it would be better to get them to actually understand JS's paradigm instead?

TS doesn't change the basic paradigm of JS, it just makes it type safe. Types !== Objects. The only real reason to use JS over TS is that it's slightly (I really do mean slightly) faster in terms of development speed. But that is definitely not worth the loss of confidence and consistency you get with TS.

Check out fp-ts, which brings functional semantics to TypeScript.

I always appreciate your comments Fernando, thanks for sparking a great conversation.

 

Ryland do you consider writing TypeScript for the sake of "type safe" is more advantageous than testing ?

If I had to choose between the two I would choose testing every time. Nothing replaces good tests.

I see, I've never used Typescript before. However, all the arguments presented by people recommending it never convinced me. I think it's kinda useless to switch for TS to only get that compile-time error hinting.

My point is why to switch if you can use the current JS ecosystem to write tests that ensure the outcome ( The business logic ) is valid, and check the types if you want to, rather than adding that semantic analysis provided by TS which gives no extra magic just a hint for the source of type mismatching ( The same as testing ). Really Writing better JS using JS itself, alongside testing, is more appropriate IMO.

JS ecosystem is complicated enough, TS is fragmenting the community.

Typescript and tests cover different failure scenarios. This article was very informative about the benefit of each: css-tricks.com/types-or-tests-why-...

Thanks, it sounds interesting. I'll give it a read

The whole "only being a compile time safety net" is something I told myself before I forced myself to give it a propper go.

The power of being able to refactor a large app without breaking something is invaluable for me.

A good example is the ability to define the type of a return from an API. If this shape changes in the future with a simple modification of your type you can now ensure that not a single part of your code base references a node which no longer exists without erroring before building.

It has solved more errors on a refactor than I can count - On any large application if you want to have any confidence modifying code it's worth the overhead :)

I'm not arguing against your use case, I'm sure TS helped there, but that can also be done using pure JS. With the proper test cases and JSON schemas put in place (I'm making the assumption you're talking about a JSON-based API), the same thing can be achieved.

Again, not arguing against your use case, I'm just trying to find one that is clearly easier to implement in TS than in vanilla JS.

My 2c:

TypeScript makes your IDE smarter, though you have to do the type definition work. Ever worked with objects with many properties (especially nested properties) and forgotten something? Or have to keep on referring back to some file where it was first defined? Or accidentally slapped on extra properties that should have been somewhere else? TypeScript won't fix the world, but it does help you to avoid these errors and I find that the intellisense improvements speed me up greatly. Functions don't just accept or return arbitrary objects: I can easily refer to structure definitions in code I haven't seen before and get good autocompletion.

Yes, you could also achieve some of this with jsdoc, but if you're writing jsdoc, you might as well define types. It will actually be quicker 🙂

TypeScript is also, imo, the easiest way to get modern syntax like async/await and import syntax. I've found it easier to set up than Babel.

All JavaScript is TypeScript, so you don't have to go "full-on" - adopt what works as you decide to. You can introduce it to an existing JavaScript codebase without having to change your existing code - it can deal with .js files and if you decide to convert some existing code, change to .ts and deal with any warnings/errors. You can also relax the compiler, but I've found most usefulness with stricter settings (like not allowing 'any') and projects where things get the murkiest have been where people avoid the typing system. My advice is to rather try to find / define the correct types than telling the compiler not to bother.

 

Well, I guess I've been neglecting my TS. I'll have to give it a try and see if types and me agree with each other :) Thanks for the nice reply and explanation!

code of conduct - report abuse