If you want to get something up and running fast, then JS/Python should absolutely be your go-to. We have an "innovation sprint" every quarter where everyone gets to try out changes and new features and anything else they wish to hack with our system, and I would say 99% of people choose to do this work in JS/Python.
However, my personal opinion is that productivity's first and most important pillar should be maintainability, followed closely by readability, with speed relatively far behind.
Again, this is just my two cents, but I equate Python or JavaScript to sending a message without things like capitalization and punctuation. Works perfectly fine for Slack, but not as well for writing a novel.
My interpretation is that the conclusion, at the moment, is that we can't know for sure, scientifically, which one is "better".
That being said, I sill have to find the randomized, double blind test that proves a hammer is the right way to hit a nail.
I agree this deserves some study. But...
> when you have to do something you don't have yet any clue about the type system is just in the way
Even if you don't have any clue, you usually know the types of your functions and data structures.
I mostly write Python and OCaml code. Each langage has its use cases, but I rarely feel the OCaml type system is in my way. When it's in my way, it's because my code is incorrect in an obvious way.
I would use typed API's though, because it saves documentation reading time and makes the editor autocomplete to work like magic.
This is not true. Unit tests cannot replace a type system, just like a type system cannot replace unit tests.
You need a unit tests because a type system cannot check for all possible types of correctness.
However, unit tests can only check for the presence of bugs; they cannot prove their absence. On the other hand, a type system can prove that certain classes of errors cannot exist in the program.
In the case of my anecdote here, I'm mostly talking about typescript, but I've worked with a bunch of other ones in a non-web context.
Every single time, without fail, when I get a "snag" from the type-system, it's complaining about something real. Sometimes it's a trifling bug, like a typo, but ... even there it's usually pretty nice to have the type system immediately jump on it and report it, without me having to deploy the thing and run it and only then find out that something is wrong.
But the other class of bugs - that's where it's solid gold. It'll often catch really sneaky bugs, bugs related to "nullability", where some object I'm blindly using isn't guaranteed to stay allocated during the use case I expect it to be useable in, and holy smokes are those a lifesaver. Having had to deal with those bugs from the opposite direction, they're an unleaded nightmare to try to fix without the type system pinning down exactly the culprit that would be causing it. Every time I see one, I immediately think "wow, this would have been a 5-10 hour nightmare if I had to fix this because of some production bug". I've been in the office till 10pm, and ... I never want to do that again if I can avoid it.
That's an usual symptom that you are trying to write untyped code in a typed language.
There are few cases where types do get in the way, but in the huge majority of the cases the types are there for you to explore your ideas on them first, and only mess with the code once they make sense.
Subjectively, my experience is that writing out the type definitions and signatures of main functions is a great way to start exploring an unknown problem space.
Being able to specify interfaces is absolutely nice, but overall I'm not convinced it's worth the trouble.
Otherwise I dunno what this could be. Especially what TS could be disallowing that'd be all of: valid in JS, a good idea in JS, and especially time-consuming to fix.
Judging by the seismic shift in the industry away from vanilla JS towards TS I'd say that qualifies as an extraordinary claim.
It would be interesting to hear some of the details behind your experience.
Most of the functional errors will be caught either by unit tests or by functionality noticeably not working. These are not things that would be caught by Typescript anyway.
The irony is that we're using typescript in the front-end, where it mostly gets in the way. I think Typescript would have been more useful in the backend, but we're not using it there, because originally our backend was trivially simple. Now that the backend is becoming bigger, I can imagine Typescript would be more useful there.
It could be that Typescript doesn't work well with our version of Vue. (I think the latest version is designed around Typescript which will hopefully make the process a lot easier.)
In my experience working with React, which is pretty heavily invested in typescript these days, if you go reasonably deep on doing typescript interfaces, it's like a switch gets flipped.
A light dusting of typescript really does barely anything; it's just boilerplate. But once you get up to about 80-90% coverage, it's like a switch gets flipped. All of a sudden it's really, really good at detecting discrepancies - I had a thing I was working on today, where I had a cute little svg icon component in the giant SPA program we're writing - I was just reusing the thing, and attaching a click handler to it, and all of a sudden - this component we hadn't touched in months, typescript starts griping about it. And I'm like "oh come on, this is so basic - what the hell could be wrong about passing in a simple onclick handler?" Well - turns out nobody had ever needed to use the "event" param on that function, so it didn't even use one internally - what I was passing in, in plain JS, would have just been thrown away, because the internal 'passthrough' version of the function had no parameter at all. And I didn't notice it in light testing (we have TS set to emit our program even if it's failing tests). I tested the component, and because the behavior's invisible/internal, it seemed like it was probably fine. Maybe I would have caught it with really earnest, aggressive testing later, but I didn't even need to - typescript just nailed it instantly.
I've had the privilege of working on some game development stuff outside of a web stack, and holy smokes does working in a complete, algebraically typed language change everything. When you go from 80-90% type coverage, to "hard 100%", it's just a complete 180°. It's just _freaky_ how good it is at catching errors. I'll change one little thing, and it can tell me "oh yeah - you know that cutscene an hour into the game? Yeah, you broke that." It's uncanny. It just absolutely changes everything about how I work.
Basically, any use of `any` should be avoided. Once you tolerate one `any`, you're on the way down.
One thing that I really, really do like about typescript is that you need to be explicit about whether a value can be null. Java lacks that, but the difference between `foo: string` and `foo: string|null` is stark.
I honestly wanted to believe in the value of Typescript and was enthusiastic about the switch, but it really hasn't proven itself over the past year.
I'm heavily biased towards small teams and small to medium programs though. I can at least imagine how TS improves ad-hoc documentation in some cases, which can definitely help in the "maintaining the code over a long period by different people"-scenarios.
For web gadgetry or exploratory ad statistics, you might end up with different productivity-enhancing features.
Strongly typed languages increase productivity if the cost of a type mismatch bug exceeds the cost of defining and specifying the types. That's true for some programs, and it's not true for others.
Dynamic typing is useful if you are forced to develop software before you understand the business model or if you need to expose some DSL to your users. I normally view it as a short term option that is typically reached for when not enough actual engineering has occurred (in more complex systems). It's also mandatory for working within certain domains (i.e. the web). I think this last point is why so many seem to think its a perfectly acceptable way to carry on in any sense.
This is an experience issue, not a type-system issue. Rapid refactoring is also possible during initial passes while design is settled.