But I would love runtime checks for types. Even if that was a compiler step I could flag on—but that makes it a great deal more complex both to implement and reason about, likely—without starting fresh anyway.
IMO, runtime type analysis is a code smell. There are few scenarios where the simpler and more efficient solution involves querying type metadata at runtime. Particularly in a language that directly supports dynamic dispatch, you should think hard before adding anything resembling an "if typeof(mything)" check.
(Reading through the thread, there’s apparently some libraries that can do this; I’ll have to try them out next time I need this.)
const shout = (message: string) => console.log(message)
into something like
const assert = require('assert'); const shout = (message) => { assert(typeof message === "string"); console.log(message); }
of course this doesn't work for more complicated types
See for example Tetris implemented in Pokémon Yellow via runtime code injection:
https://www.youtube.com/watch?v=Vjm8P8utT5g
Their compiler missed that!
So I think there's good reason to switch from talking about types as "assumptions", and think of them as compile time "assertions". Something lower-level in the stack could break the high-level code, but that doesn't make the high-level code useless, just imperfect.
Types can and do affect the way programs run at the lowest level. Perhaps someone with a better understanding of compiler theory can elaborate further on this...