For checking the type of untrusted input, like a JSON response, then yes, type-check functions are equally useful in both TypeScript and JS worlds.
...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).
Thank you so much for expanding on what you knew I was trying to say about introducing additional type guards. Yes for casting from JSON you'd still need to inform JS to treat something as a string or float or int before using it, but with overloads and utility types in TS it becomes much more interesting and subtle to keep the compiler happy, and that is what ultimately leads to highly maintainable code, i.e., zero problems at checkout. And zero use of "any". The reason "any" exists and is a coding horror is because JS and the kind of code people write without type checks is a horror.
...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).