Null safety that actually works
How Havran collapses null and undefined into one predictable model that lowers to clean JavaScript — no wrapper types, no runtime cost.
Most "null safety" in JavaScript land is a library or a linter rule. In Havran it's part of the type system, and it compiles away to nothing.
One nullable model
A nullable type is written with ? . It lowers to a | undefined union — no boxing, no wrapper class:
| Havran | TypeScript |
|---|---|
val x: String? | const x: string | undefined |
x?.y | x?.y |
x!!.y | x!.y |
x ?: "other" | x ?? "other" |
Havran uses null in source but emits undefined by default, so it lines up with how the JavaScript ecosystem actually behaves. When you genuinely need a literal null for an external API, opt in with @JsNull null .
The compiler does the work
Because nullability is tracked at compile time, member access on a possibly-null value is a compile error unless you handle it:
fun initials(name: String?): String {
// name.first() // compile error: name may be null
return name?.first()?.uppercase() ?: "?"
}function initials(name: string | undefined): string {
return name?.[0]?.toUpperCase() ?? "?"
}A few rules worth knowing:
-
!= nullchecks for both JSnullandundefined. -
?:is the Elvis operator — a fallback when the left side is null. -
!!asserts non-null and lowers to TypeScript's!.
Null safety should be invisible at runtime and unavoidable at compile time.
That's the whole trick — and it costs you zero kilobytes.