The kernel itself does not consist of any shell scripts. It may have them for building the kernel, but just like the shell scripts at boot, the problems solved there are much simpler (mostly call compiler and linker on a set of files). So I agree: For simple high level problems a dynamic language is sufficient.
As to your second paragraph, I do agree that C has a vastly insufficient type system from the 70s (even though I think better type systems were already available at the time, but the inventors of C might not have known or cared about that). Rust solves the problem you described, and what you complain about is actually that errors in C tend to be represented not statically enough.
That is an interesting aspect about rust I have not heard, and since over 50% of my C code tend to be about managing return codes with proper tear down, rust suddenly do look a bit more interesting. However doing a surface look, it seems that rust simply terminate the program when encountering some of the more critical return codes from syscalls, which does exactly feel like it solves the problem. I guess it is also a reason why the kernel might not switch to using rust any time soon, as oom should not cause drivers to just terminate hard. From my surface look, it also seems rust simply uses Result<> where in C you would store the value in an int, and both leaves it up to the user to read the manual and interpret the number into actually meaning. Of course I could be wrong.
In a way it also demonstrate a other line between when I would use shell, Python or C. With shell everything either existed OK or did not, and the return data is always strings, and so the programs written there is built with that in mind. With python I work with structured data, but I don't spend much work or thought on syscalls and what state the machine is in. With C, syscalls management and the state of the machine is the majority of the code. As such one pick the language based on what the code will be focusing on. Dynamic vs static basically becomes a shorthand for that focus.
As to your second paragraph, I do agree that C has a vastly insufficient type system from the 70s (even though I think better type systems were already available at the time, but the inventors of C might not have known or cared about that). Rust solves the problem you described, and what you complain about is actually that errors in C tend to be represented not statically enough.