Earlier quoted context omitted.
> Being dynamic doesn't preclude variables from being type checked by the runtime. It kinda does, because in a dynamically typed (as colloquially defined - if you want to debate that definition, that's another discussion) language, variables don't have types - values do.
Ok, if you want to be pedantic about it, fine. Nothing precludes values from being type checked.
There are contexts in which two values are involves, where we can at least check that the types are matching (or reasonably compatible), like (a + b). JS is a massive failure in that regard, too, and there are dynamic languages that do it far better - e.g. in Python, ("1" + 2) is a runtime type error, not 3.
But in the context of this thread, I feel that's not what we're talking about. We're really talking about contracts - and contracts require typed bindings (variables, function arguments etc), not just typed values. Which means that they do require static type annotations. As we've discussed in another subthread, those annotations might be checked dynamically - but they still have to be declared statically by the coder, which makes the type system effectively static from their perspective.
To put it differently: if you require types to be declared explicitly, there's no reason to not check them statically. Dynamic checking of static types really only makes sense for gradual typing systems, where code with static type annotations might be called from some non-annotated code, and you want it to be possible without forcing static typing on the caller. At that point, yes, you can have a dynamic type check in the callee, which ensures that if code without type annotations doesn't actually get the types right, things fail fast at the static/dynamic typing boundary, instead of allowing it to propagate into the statically typed code (as is the case in e.g. TS today).