C’s type system is unsound, and not all compileable programs respect its dynamic requirements. We cope with this by referring to some code as “not type safe”.
foo bar = NOT_FOO;
You say this “typedef enum {…} foo” is not a type, naming a set of values, but just a convenient alias for whatever the representation is, thus all “enum” (regardless of actual decl) name the same set, and every constructor expression shares the same “type”. Consistent with the language specification, and passes the type checker, so you could say this code is “type safe”? but it’s one hell of a foible and not consistent with any lay (non PLT) understanding of type safety, where typesafety means the type written in the code and the runtime representation won’t desync (no runtime type errors).
If you simply forbid UB and refer to only strictly conforming programs, I will accept this modified meaning of “type safe”, but grumble that this meaning is not very good
edit to encompass parent edit: as a typescript nonprogrammer, I have nothing to add :) I am confused why you are putting the features in opposition. gradual + value-sensitive typing is a good feature, but doesn’t conflict with sums. in ocaml, we support both, real sum types as well as variant [`A | `B] etc that are structural in the way you’d want C to be