Integers are the worry.
the JIT being able to say "This here is an int, which means that this function takes an in and returns an int always, i'm going to compile it that way" means that now that function is "C-Speed".
If your program were filled with functions similar to that where the compiler is easily able to optimize the shit out of it, then it will run suprisingly close to "C-Speed".
Custom types (which I took to mean different data storage formats) aren't really something that the compiler can help with (any compiler). If you use a hashmap, you've got a hashmap, if you use a doubly-linked-list you've got a doubly-linked-list. C or JS iterating over an entire hashmap is going to be slower than iterating over memory addresses.
But luckily JS has stuff like TypedArrays which are basically C arrays with bounds checking.
And if you loop over it in a way that the compiler can determine you won't go out of bounds (say, with a simple for loop that runs while x < arr.length), you've got memory access at C speeds.
So you "can" (technically, on paper) make a JS program that would run at C speeds in most cases, but at the end of the day some part of your stack is going to begin using the dynamic parts of the language, and then you get the big speed roadblocks again. (by the way, the above is basically what ASM.js is, a well curated subset of JS which doesn't allow anything dynamic so that the JIT can compile it to run at "C speeds")
The benefits of a static language aren't in what they allow, but what they don't. Tying your hands and saying "No, you can't make an array of half strings and half integers" lets the compiler be simpler and not have to worry about those "edge cases", which means that it can focus on the "fast path" more. (in practice this almost always shows up as a faster language because JITs aren't perfect, so they can get confused by code that could technically be compiled more optimally but won't because the JIT can't identify it)
It's also why adding optional static typing to a language won't make it faster on it's own (after all, the JIT already knows what types variables are at calling time, telling it that again won't solve anything...)