There seem to be two conflicting views regarding the status of "type systems" used in dynamically typed languages:
That dynamically typed languages are actually just unityped static languages. From what I can tell, the majority of type theory literature for programming languages (e.g. Types and Programming Languages) focuses only on statically typed languages, where by definition type checking is performed at compile-time. From this viewpoint, it seems reasonable to treat dynamically typed languages as being unityped.
On the other hand, the runtime engines of popular scripting languages like Python and JavaScript check the types of expressions during the program's execution, and raise an exception if there are any type errors. This feature seems to be common in dynamically typed languages, and is colloquially referred to as "strong typing" (although this term is discouraged). In the literature, it seems standard to refer to these runtime types as "type tags".
Even though dynamically typed languages don't have genuine type systems according to the definition in point #1, it seems like many ideas introduced in type theory (e.g. polymorphism, subtyping) are directly applicable to understanding how these dynamic languages behave at runtime. Conversely, it seems reasonable that we could run a statically typed language line-by-line (e.g. in an interpreter) and handle type checking in an identical way to the method described in point #2.
So, my specific questions are:
How useful is type theory for understanding dynamically typed programming languages?
Are there any formal theorems showing a direct correspondence between "static types" and "runtime type tags"? Can we just replace the word "type" with "type tag", and perform the type checking at runtime instead of ahead-of-time, and then think about the programming language in terms of static type theory? If so, are there any limitations to this approach, e.g. situations where the analogy between "static types" and "runtime type tags" is no longer valid?
"3" * 4
is12
(instead of "3333"),"9"**"2"
is81
, and"string" / [1, 2, 3]
isNaN
. The only ways I can think of to get a type error in JS are trying to access a property of something that isn't an object, and trying to call something that isn't a function :D $\endgroup$