I find it odd that is was a remarkably long time before I give a good answer to this. Perhaps only when I played with Dart did it become clear even though the answer is really simple. So not to be one of those YouTube videos or long articles that try to hide the information you are after in the hope of getting ad clicks.
A type system limits the number of programs you can create using a given programming language.
That's it! Well that is my definition and I am going to deconstruct that statement for the rest of this post. But honestly if all you remember is that statement then you are good.
The idea is that a type system helps you avoid making mistakes by reducing the number of incorrect programs you can write. It checks what you have written is not going to do anything stupid. Of course the type system is always limited in what it can check and stupidity knows no bounds, at least based on this programmers code anyway!
Alas there always seems to be collateral damage, so as you restrict the bad programs the type system starts to remove some of the good programs as well.
And that's the trade off in type systems.
Languages like Rust disallow things in the safe part of their language but allow extra things in the unsafe part. Effectively creating an escape hatch. I think that's a great idea.
As the type system get stronger it gets increasingly difficult to write a program. When it runs you have less chance of bugs. You trade iterations times for guarantee of correctness.
If good type systems allow you to write programs more likely to be correct then why wouldn't you use the strongest one you can. Ignoring resistance to change I can think of a couple of valid reasons
- Iteration times are important. Finding the fun in games is the classic example here.
- Accessibility, while professional programmer may like stronger typing. Scientists, artists and people in other professions often don't want to spend the time learning them and just want the code to work to get their job done.
- I guess teaching, convincing someone about strong type systems when they are still learning the abstractions required to code is going to be a hard sell.
Dynamically typed programming languages still have a type system just it is checked at run time. You have to rely on a really good test suite to exercise as much of your code as possible or just hope for the best.
At one point dynamic typed languages where more concise to write but over the years mainstream statically types programming languages have increased their conciseness, primarily using type inference. It is fair to say the world has shifted to static typing over the last decade. With dynamically typed language such as Python offering optional static typing they do now offer the ability to use gradual typing, or hardening of code you feel is not undergoing much change and is now well thought out.
I admit to having a preference for statically typed languages but do feel everyone should experiment with a few languages and use what fits. This assumes you are into coding, I would be susprised if you were not and reading this.
Using Dynamically typed languages taught me a great deal about trying to code as simple as possible so it is easy to spot mistakes.