I just figure, everything is coming in as a string no matter what. It's going back out as a string. The only place it needs to be anything other than a string is something interesting is being done with it and since dynamic typing lets you just worry about it in those cases, it removes a lot of unnecessary code.
On the flip side, outside of web work i can't imagine the reverse.
Maybe so, but that only accurately describes things at the boundaries of your system. Your database tables still have columns that hold integers, dates, or floats. Sure, you could do the type coercions as needed, but at that point you're missing out on the valuable opportunity to validate your data as it enters the system. You can provide meaningful errors to users as early as possible, you can avoid defensive checks nearly everywhere else within your code, and you can just generally trust that invariants about your data are going to hold throughout the rest of your program.
This leads to smaller test suites, more concise codebases, and higher security assurances overall. If you look at the sorts of vulnerabilities that often pop up in Rails for example, many of them simply don't affect you if you use something like Virtus [0] to validate the types of your data as it enters the system.
I don't do much web development, but statically typed web development is the only way I've ever been able to tolerate it.
Here are a couple of other under-appreciated facts about compilers:
1. For regular grammars, they are easy to build with any kind of programming language.
2. For regular grammars, they are really really easy to build with statically-typed programming languages.
Now days, my web development is essentially just compiler construction for regular languages, and it just so happens that extremely statically-typed like the MLs (F#, in my case) are damn good for writing compilers (one joke is that it’s the only thing they’re good for). I write far fewer lines of code per feature than I ever did with ”dynamically“ typed languages like PHP, and it’s usually right the first time.
If you're comparing two different designs in a statically language where one involves making lots of new types and the other just shuffles strings back and forth, then I can't say and it'd depend on the specific case. Generally, helping the compiler is a good thing, and obviously things like switching on an enumeration is much faster than a long line of string comparisons. Actually, strings are just a horrible datatype, so unconstrained and inefficient. Use strings less!
And everything in memory is a sequence of bytes. I don't see the relevance of this line of reasoning. I guarantee that whatever experience you've had with statically typed languages on the web, it's not a good language. Interfacing with dynamic systems is simply a matter of good abstractions, which many languages simply lack.
Take a look at F#'s type providers to see where you can go with this.
You might also be interested in Elixir which ties in to the Erlang ecosystem, but if you are super into OOP (like me) you might find it slightly more difficult, but since you have experience with static-types, you probably know some FP stuff, and so it's not that bad.
Either way, best of luck. It takes a brave soul to fight with Rails. I've been writing Ruby for about three years now and still haven't touched Rails just because I can imagine how little fun it is to try and debug dynamic-typed web stuff. Noooooo thanks.