A shield over a blue gradient
← Back to blog

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:

HavranTypeScript
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:

Havran
fun initials(name: String?): String {
  // name.first()  // compile error: name may be null
  return name?.first()?.uppercase() ?: "?"
}
TypeScript
function initials(name: string | undefined): string {
  return name?.[0]?.toUpperCase() ?? "?"
}

A few rules worth knowing:

  1. != null checks for both JS null and undefined .
  2. ?: is the Elvis operator — a fallback when the left side is null.
  3. !! 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.

← Back to blog