I'm sorry, but how does a seasoned Javascript developer ignores the absence of compile-time type checks? Aside from switching to a language that compiles to Javascript.
I'm sorry, but how does a seasoned Javascript developer ignores the absence of compile-time type checks? Aside from switching to a language that compiles to Javascript.
If I needed compile time type checks for a snippet of code, I would use a language with compile time type checking that compiles to JavaScript.
If I needed compile time type checks for many snippets of code, I would take a few days off and rethink my architecture. Ask myself why my call sites are so brittle or confusing that I am making frequent type errors.
Why is it suddenly a foregone conclusion that seasoned Javascript developers all want compiled statically typed languages?
Please argue with me, because I _want_ to be convinced. I'm trying.
It may be because of the habits I developed, writing compiled code. I always would first concentrate on my concepts, things that I want the code to do, data and flow structure - while keeping all errors (even syntax) silent. And only when I got everything I wanted implemented and consistent, I would turn to a compiler to quickly fix all mismatches in API, all wrong method names and other trivial blunders.
Now I stumble, feeling that I'm a blind man going through a minefield. Every line I write, I have to think about the things that I want to express and the mechanics of language and API simultaneously - because nothing's got my back. (Yes, I know that I should write unit tests, but not all of us have the luxury of working on perfect projects, starting perfect projects from scratch, or having the resources of putting good practices into legacy code).
Every time I discover that I mistyped the name of the function or variable, forgot to use "this" when referring to an object property (C# habit), forgot that external API function returns a custom type and not a string - I do it too late. Instead of quickly fixing the thing that I've only typed right now, I have to go back, and spend time reading and understanding relevant code again.
All I'm trying to understand is, where are the trade-offs? Where are all the awesome dynamic things that make all that worth it?
I like Javascript, and that's enough for me - and I (in _most_ situations) find dynamic typing more of a benefit than hindrance; but I don't mean to purport that my perspective is everyone's perspective :-) IMO it's very plausible that dynamic typing will never be better for you; because we're all different and we don't all like the same thing. If you've come to learn that dynamic typing doesn't suit you, act accordingly, don't just try to change yourself because something else works for others.
If you're interested in static typing, maybe try moving to Typescript? AFAIU it also integrates fairly well with normal Javascript, and hence maybe it's more to your taste? And if there are other people feeling the same way you are on your projects, it mightn't be too difficult to move new (or maybe a subset of new) development to something more your taste instead? (I've heard good things about Flow as well, and maybe it's simpler to "sneak in" to your projects, and offers big enough benefits for you?)
In my experience, legacy projects (or projects where there's pressure to cut corners (eg unit tests)) are often the bigger issue than the language. (eg I've been "in pain" working with code in languages I otherwise like that was obviously done in a big hurry, or evolved obviously from clumsy requirements and hence has big inconsistencies.
(As an actual example of a reason _that applies to me_, the last Javascript project I worked on ran the integration tests faster than the last compiled statically typed project compiled (and reloaded) - hence I ran the tests in a watching process, and felt more productive and less frustrated. And yeah, I haven't written `this` for a very long time :-p )
Type Checking vs. Metaprogramming: http://www.oilshell.org/blog/2016/12/05.html
http://www.oilshell.org/blog/2017/01/21.html (at the end, pretty printing requires metaprogramming, or escaping into another language)
Whenever you have a code generator like an ORM, or protobuf-like schema languages, you can use metaprogramming instead. Generally I think this helps the program so you don't have these impenetrable walls between layers, where one person understands one side and the other person understands the other.
I find that a lot of programmers coming from statically typed languages are writing Java in Python, or Java in JavaScript. In Java you don't really think in terms of metaprogramming.
If that's the case, then it is going to feel annoying. You're getting all the downsides without any of the upsides.
I would look at Go for other examples of the downsides -- namely the lack of generics. Go is attracting a lot of Python and Ruby programmers.
In Go, you can't write basic generic functions like max(), map(), filter(), and sort() -- in JavaScript and other dynamic languages this is not something you would think twice about.
I guess between metaprogramming and generics, dynamic languages let you write more abstract and concise programs. Programming in statically typed languages feels repetitive to me, and the architecture is quite clunky unless you are doing textual code generation.
Steve Yegge also has a bunch of good posts about dynamic languages.
Thanks for the honest question. I think it's important to remember that there are tradeoffs. I fully admit that type checking is useful in many circumstances. I would like the best of both worlds. I'm a little disappointed that recent hybrid languages like Dart and to some extent Racket have had problems with optional typing and gradual typing. It is something I'm interested in but it seems like an unsolved problem.
Thanks for "When Polymorphism Fails" link, it was a wonderful read. I've actually run into such situations a couple of times - but in my experience, you want most of your methods to be statically checked, and only a minority of them to be added and checked dynamically in runtime. May be the solution is to have two different method tables, that look and behave in a different way?
However I will point out that probably 80% of the world's top websites are written in dynamic languages -- Wikipedia, Facebook, Yahoo, YouTube, Reddit, etc. (that's not even counting the JavaScript.)
So there is something about that use case and dynamic languages... That's not to say a language is great because it's used widely. But it means that it must be getting something right, and not doing other things too badly.
So yeah all I'm saying is that there's a tradeoff. If there's was no tradeoff, then it would have never have swung toward dynamic languages in the 90's/2000's. It's not like we didn't have statically typed languages before the web. But things swung that way, and it sounds like they're swinging back, with PHP, Python, and JavaScript all getting optional types in one way or another.
The language is constantly being improved while maintaining backwards compatibility. Finally it's ability to handle whatever kind of data you throw at it until you choose to check the data is a strength in an environment (web pages) where nothing is certain. You aren't sure about the data you will get from an API, from the user, you don't even know what kind of environment your code will be run in! The same code might run on the latest version of Chrome, a headless test environment, or some old version of Internet Explorer. And that is totally possible. It's all up to how you code it. And you have to get used to coding in this type of language. You can and should test your code as you go along, no need to wait to compile, you can see the results right away. Build your code to handle errors, because even if the code is perfect, the data you are working with will not be. And have lots of tests. Not only do they identify current errors in the code, but they allow you to make large changes with confidence that everything else is still working like it should.
I jist can't deal with the sloppy wild west way Javascript world works.
Now, if you're writing a programming language, this probably seems pretty awesome...
For example, it's common to use Flow with Javascript to enable static type checking before actually running it.
The language itself doesn't guarantee type safety, but when used with peripheral tooling, the developer isn't missing too much.
Really, I find compile time checks to be moot when you have fast running and good unit tests.
A by product of testing your logic is that it will fail if there is a type cast problem.