I would say that dynamic metaprogramming is at odd with type checking (and optimizations, and in general understanding the behaviour of a program statically). But of course metaprogramming can be done perfectly fine in a statically typed language.
My blog posts give some more color on that, but also see:
Also, OCaml has had at least 4 different metaprogramming systems -- ocamlmeta, camlp4, ppx, etc. Rust is getting its second one post-1.0 as AFAIU.
There are lots of open problems related to metaprogramming and type system design because they interact heavily.
This blog posts also hints at that: https://nim-lang.org/araq/v1.html
In contrast, in Lisp, metaprogramming is "just programming".
Also compare with C++ metaprogramming (whose syntax is certainly awful, although it has been continually improving), but works perfectly fine with its type system (in fact most metaprogramming in C++ is done via the type system).
On the other hand CPython also exposes the runtime internals to plugins and de facto that prevents the language from evolving and alternative implementations to gain a foothold, so the issue of exposing implementation details preventing language evolution is not restricted to static languages.
edit: the hard part of typing and metaprogramming is making sure your metaprograms are well typed, i.e. the generated program is guaranteed to typecheck. This is great, but it is not a strict requirement, if you are happy with syntax macros a la rust or unconstrained templates a la C++, there is no particular issue. Your genrated program will be still be typechecked at compile time, which is still better than having a runtime error because of a bad metaprogram.
It's exactly analogous to types being integrated in OCaml, Rust, etc. whereas in Python, JS, Ruby, and PHP static typing it's an "add-on".
Scala also has a newer system https://scalameta.org/
C++ has new dramatic new proposals 20+ years after templates, addressing really basic use cases:
The point is that no language has gotten it right so they keep introducing new systems and breaking old ones.
C++ templates also have the mistake where type checking is done after template expansion. That's why you get terrible error messages.
If you're not convinced, that's OK, but try watching the talk by Yaron Minsky here: