Just use dynamic or better yet type-tag-free languages. Types are hard to get right and hard to reason about. Sure, there are some Sheldons out there who master it even under pasta applications, but most of us are not Sheldons. C# also bleeped up types by adding nullable types, making reflection into a scavenger hunt.
For dynamic or tag-free languages, type indicators could be used to parse-check scalar (base) values to see if they are interpretable as the intended type:
function foo(int a, date b) {...}
This would be equivalent to:
function foo(a, b) {
if (! parsableAsInt(a)) throwTypeError(...);
if (! parsableAsDate(b)) throwTypeError(...);
}
And don't overload operators, such as how some languages use "+" to mean both arithmetic addition and string concatenation. Use a different symbol for concatenation like PHP does.
You have to reason about types in any language because passing the wrong type to a function can result in errors. You have to do all of that mental work by yourself in a dynamic language because there isn't a system to do it for you.
There are tools roughly similar to C's "lint" that can warn you about suspicious-looking code. While compile-time checking can be nice, compiler-oriented languages often result in more verbose code. Verbosity introduces errors also. But the benefit weighing also depends on the kind of applications. I didn't mean to trigger a "holy war" of static versus dynamic languages.
I understand that, but I'm not sure the benefits exceed the drawbacks. In other words, verbosity introduces errors by making the code harder/longer to read. The type-related verbosity may reduce errors, but perhaps not enough to counter those caused by verbosity. In my experience, it's roughly a wash, but depends on a lot of other things, like frameworks used, skill of developers, QA techniques, etc.
That would solve the problem with adding generics, yes. It would also destroy the thing people appreciate about static typing - that you get told at compile time when you've done something wrong.
For dynamic or tag-free languages, type indicators could be used to parse-check scalar (base) values to see if they are interpretable as the intended type:
This would be equivalent to: And don't overload operators, such as how some languages use "+" to mean both arithmetic addition and string concatenation. Use a different symbol for concatenation like PHP does.