i love typescript, but that's still not the same as static typing. imagine a full stack typescript app with a blog type
type Blog = { name: string }
everything works fine until you decide to refactor "name" to title. you update the backend and typescript code and deploy the change
type Blog = { title: string }
user john never closes his browser and leaves your website open. he clicks on a new blog post. his client typescript expects a name, the server gives a title, and crash, "Cannot read properties of undefined".
i still choose nodejs backends, but you obviously have to keep in mind it's not statically typed. same with "any", my coworker could take my blog and modify it. it's preventable, but with large teams and codebases still prone to error.
TypeScript is definitely statically typed. It is not a 100% “sound” type system, but very few languages actually are (Haskell, Reason, etc)
And in your example of loading data from a server, if you have appropriate lint rules set up your editor and linter will warn you when you pass “any” typed data (such as that returned by fetch’s response.json()) to something expecting another type. You can use something like zod or yup to validate the data is the type you expect before passing it the rest of your typed code, thereby containing possible type errors to a known location where you can gracefully handle it.
This is a problem with any language that accepts typed data from an external system, certainly not unique to TypeScript.