More seriously, JS has had its own resistance movements. TypeScript was actively disdained until, as far as I can tell, Angular switched to it. Probably partially because it was MS, but also because there was a lot of resistance to static typing despite the demonstrated safety benefits.
Do they really help enough to be worth it?
(Other things, like liability from bugs and crashes, may give an edge to static typing. The age-old debate is how much)
I never find that static types force me to plan more – it's pretty easy to change them on the fly.
I frequently find that static types let the IDE highlight an error the second I write it, instead of waiting until running tests. And every codebase I've worked with has taken at least a few minutes to run tests (and sometimes much longer), so this is a pretty substantial savings.
Or in other words, static types free me up to be more creative, by requiring me to spend less energy & attention on certain types of errors that were common before.
Recently I needed to fix some things in the original Ruby code, and it felt like freeclimbing after getting used to ropes... I called a function and started wondering how I could have any guarantees that it returned something useful. Benefits of static typing really ‘clicked’ for me at that moment. I still love ruby though
Duck typing only works when it works, which is not as trivial a statement as it might first seem.
Think of it this way: you only ran it 10 times, are you sure you found all the bugs? What about 11 times? Are you sure you found all the problems? Numerically speaking, if the first 9 attempts didn't work, then 90% of the time you ran it after coding, it was still broken. The fact that the program was broken a majority of the time you developed it should make you skeptical if it's even "correct' after you've determined it to be "finished". I understand you picked random examples, but this is still relevant.
It seems to me like you're arguing a common argument about picking tools which is "I've always done it this way, and it works for me, so why look for anything better?"
What are these 'interpreter errors' that you write of? It is actually quite unusual for someone to find even just one error in the interpreter for each new program he writes. What interpreter are you using?
One thing I can be pretty sure of: Wall, Van Rossum, Matsumoto and Hickey didn't produce their languages without some insightful thinking ahead.
At university, it was a meme that no one's C program ever compiled the first time they tried.
I can't imagine even the best programmer in the world can avoid that kind of problem, without static analysis and static typing. Maybe you can have a 90% success rate on short programs, I'd believe that (my first-compile success rate on AoC was closer to 50%, and I was like #30 or so on the leaderboard [1]). But to do it perfectly, in real-world code? That I don't believe.
The nice thing about static typing is about catching mistakes earlier, and making it easier to figure out what your mistake was. Without the type annotation on the function, when you get a crash a few days later, it's harder to figure out "is the function wrong, or is the code calling the function wrong?" With it, those questions are automatically answered.
The best I've heard is that for short scripts, static typing doesn't help _enough_ to be worth the extra time it takes. But with modern type inference, it takes very little extra time at all.
And the extra time it does take, to write out interfaces and stuff, you can avoid in TypeScript with type assertions and `any` assertions. But honestly, it's usually worth it: It's not like you _don't_ plan out the interface; you just used to keep them memorized instead of writing them down, and then regret it a few weeks later when you want to make a change.
[1] To be fair, it was 50% because I was optimizing for programming speed for the leaderboard rather than accuracy; I'm sure I could have gotten closer to 90% if I were optimizing for accuracy. But anyone who argues that avoiding static types saves time has to accept that you make a lot more mistakes if you're trying to save time.
Ah but see, the compiler is a guard-rail. Technically, it's a static-analyzer. I don't think anyone is against making existing guard rails more helpful via editor integration; the conflict comes with adding new guard rails. Take the following example:
let foo = {
bar0: 12,
bar1: 14,
bar2: 16
}
// example 1
console.log(foo.bar0);
console.log(foo.bar1);
console.log(foo.bar2);
// example 2
for(let i = 0; i < 3; i++) {
console.log(foo['bar' + i])
}
Example 1 can be statically verified by a JavaScript type checker. Example 2 can't. There are advantages of being able to do the second thing - more code reuse, possibly less refactoring needed. But it's impossible to verify that those properties exist on that object without running the code. The argument is that oftentimes, the type checking is more valuable than the loss of "creative" freedom. But it does mean limiting the kinds of things you can do.Yes, I agree. It's a guard-rail which is missing in scripting languages like JavaScript and Ruby, and which some people are resisting adding.
> Example 1 can be statically verified by a JavaScript type checker. Example 2 can't.
With type assertions, it's not really limiting at all. For instance, I'd write example 2 as:
for (let i = 0; i < 3; i++) {
console.log(foo['bar' + i as keyof typeof foo]);
}
If you weren't as experienced with TypeScript, you can also just throw around `any` assertions until the problem goes away: let foo: any = {
bar0: 12,
bar1: 14,
bar2: 16
};
Or if you wanted to be tricky, you could even just assert a specific key: for (let i = 0; i < 3; i++) {
console.log(foo['bar' + i as 'bar0']);
}
It's true that there are a lot of things typecheckers can't check. But that's no reason to give up on the things they _can_ check.https://i.imgur.com/DJjzPDF.png
Well, it's allowed in that it will still compile the code (because TypeScript is a superset of JavaScript), but it'll still yell at you.
https://www.typescriptlang.org/play/#src=%20%20let%20foo%20%...
This statement can be statically analyzed using the inferred static types that are already present. There is a lot of idiomatic javascript code that already has inferr-able static types in it. In fact, if you turn on the "implicit any" option in the typescript compiler, then you never need to add any types.
A linter can look at anything from micro-quality like "don't use more than one ++ operator at the same line" or "there's an = at this if test, this is probably wrong" to macro ones like "I couldn't prove your program terminates", "I couldn't prove that memory does not leak", or "a deadlock can happen here".
Complex JavaScript codebases used to mostly be this way, but in recent years the JavaScript community has seen a huge influx of new, inexperienced programmers. There are obvious downsides to this, but one upside is that they don't have the pretense of being able to do everything perfectly without help, making them less resistant to things like TypeScript.
* Beginner: doesn't know much and knows it
* Intermediate: knows a lot, hasn't lived with the consequences
* Expert: knows a lot, including when not to use what they know
The two comments here seem to be articulating the community shifting between I->B and I->E respectively. I think it's safe to say we have both a maturing developer base and a huge influx of newbies. That intermediate "look what I can do!" stage still exists, probably as much as ever, but is being professionally tempered by the caution inherent in the other two cohorts.
The Intermediate stage is the most fun to watch, though, and probably a lot of what drives innovation. The coolest projects come from people who ostensibly should've known better than to try that thing.
And, funnily enough, back in my C++ days I remember dabbling in Common Lisp and loving that there were macros that achieved similar results.
Too many posts reduce this to some sort of "magic of lisp" message. Which is certainly fun, in many ways. However, I think most of it is just a lot of hard work that was done by folks. Much of which will never be considered by the rest of us, almost solely on lack of information.
So, yes, I imagine in many ways it is harder. Doesn't make it impossible, though. And indeed, most type checking can be almost trivially done. As an example, typechecking the arguments to a format command. Trivially easy in most invocations. Only when people do build up dynamic programs is this hard. Thing is, those programs are hard to even think of, so most of us don't write them.