Go has a quasi macro system though (go generate)
https://gradha.github.io/articles/2015/01/the-day-go-reinven...
I like the macro systems in Crystal and Haxe (reifed macros)
https://haxe.org/manual/macro-reification-expression.html
https://crystal-lang.org/reference/1.8/syntax_and_semantics/...
I think C would have benefited from such system at the AST level instead of text substitution.
Javascript is dynamic enough there is absolutely no need for Macros.
TypeScript macroses would be very useful for the same things codegenerators are useful: for example generating api client from swagger schema. Ofc you can do some trickery with metaprogramming, for example build and eval strings on fly and the result could be a dynamically generated function, but the point is: we want the process and the result to be typesafe and efficient, which is what is missing with hacky dynamic metaprogramming approaches.
Macros are bad and you're bad if you use them. This has been essentially a de facto mantra since the early 90s (when I was a wee lad) and it's quite common to see people writing very long articles on why you shouldn't use them[1]. They are magic, so should be avoided.
There's a reason languages like C# or Go don't have them, and you should take heed of the very smart people that designed these languages. Even in Rust, they are controversial[2] (the most obvious reason is that your IDE is worthless when macros are involved). Metaprogramming (i.e. macros) adds extreme complexity (in some cases, pre-runtime-Turing-completeness) with many footguns, including the classic, and very "fun," double evaluation.
Here be dragons.
[1] https://www.linkedin.com/pulse/why-considered-bad-practice-u...
[2] https://www.reddit.com/r/rust/comments/taxfe3/what_are_the_p...