...and when types are within TypeScript's sphere-of-influence the compiler is largely able to deduce types without needing assertions or type-checks.
...or so you think! But there's two problems:
1. TypeScript's type system is unsound: so there are times when the compiler will let you do some (for example) contravariant array mutation, even though that's almost essentially guaranteed to crash at runtime if the rest of the system makes incorrect assumptions about the type-variance of the array/collection. So having the type-guard function available to assert to tsc that whatever array operation you performed is safe, you wouldn't need to do that in pure JS.
2. Type-guards are essential for when you're working with values that pass through an interface (because that necessarily means some loss of typing information has occurred), so the type-guard function is needed to recover that static information - and while this approach does also apply to JS, in some situations where if your code is the factory of subclasses that pass through an interface (e.g. so `MyComplicatedSubclassForRockAndRoll` appears as `MusicSubclass`) then in JS a blind "reinterpret-cast" of the object is fine - but TypeScript really doesn't want you doing that and again, having a type-guard function is just to keep the compiler happy - and even if it is possible to mathematically prove that the `object` type-cast is correct (because theoretically static analysis can see on both sides of an interface) but TypeScript isn't perfect and there are cases where we really do know better than the compiler, but we don't want to just make it unsafe and untyped - instead we want to keep the typing and we want to keep the compiler happy, but doing it this way (a type-guard) is not only easier than suppressing warnings and ignoring your sense of guilt but they're invariably genuinely useful a few months down the line when someone made a change that the type-system spotted and prevented from compiling (and so going into production), whereas it would be very easy to (for example) unintentionally introduce vulnerabilities because even with near-100% test coverage, because adding brand new functionality to a project (even if it said functionality doesn't work) it won't cause any tests to fail (at least, until tests for the new functionality are completed).
If it's an external API, do the same thing except it probably needs a more manual approach.
This is not something that's in anyway unique to typescript. The difference is JavaScript is designed to fail gracefully using coercion whereas most other languages and runtimes abort and throw exceptions.
the web runs on JavaScript because it's extremely forgiving and therefore stable. there can be lots of errors and things keep chugging along.