Kotlin actually comes quite close. If a value can be null, it's treated differently. If I have a function that always returns a string, it returns "String". If I have a function that returns either a string or null, it returns "String?". That question mark makes the compiler treat it as an entirely different type in many cases.
Any argument that expects a "String" will not accept a "String?" without first checking to make sure it's not null or by nonnull asserting it, which essentially means you're pinky swearing that a string will definitely be returned in that given scenario. You can use it irresponsibly, but you have to go out of your way to do so, unlike Java where null pointers are the default behavior.
Another cool thing you can do is the "?." operator. It basically means "do an action if the thing isn't null, and if it is, do nothing". So myVal?.toString() would stringify myVal if it's not null, and do nothing if it is. Technically it makes toString return null, but in practice it usually means it does nothing.
I think the way null values are handled is my favorite thing about Kotlin actually. It makes null pointers almost impossible unless you code like shit on purpose and nonnull assert everything no matter what. Which I don't doubt many programmers do.