Coming from JavaScript

If you have written TypeScript, the type annotations will feel familiar — but they are not erased: they compile to layouts and to native code. And the surprises JavaScript keeps are all gone: one equality, no coercion, no undefined, no this that changes meaning by call site.

ConceptJavaScriptKeal
Bindingconst x = 1val x = 1
Mutablelet x = 1var x = 1
Functionfunction add(a, b) { return a + b }func add(a: Int, b: Int): Int { a + b }
Arrowxs.map(x => x * 2)xs.map({ it * 2 })
Array[1, 2][1, 2]
Object / Mapnew Map([["a", 1]]){"a": 1}
Template literal`hello ${name}`"hello ${name}"
Null checkx ?? "d"x ?: "d"
Optional chainx?.lengthx?.length
Classclass C { constructor(n) { } }class C(var n: Int)
Promiseawait f()actors: spawn / send / run

What will surprise you

One equality, and no coercion

== compares values of the same type; there is no === because there is nothing to distinguish it from. "1" + 1 does not silently become a string of digits — although "n = " + n is allowed and renders the value.

null exists, undefined does not

One absent value, in the type or not at all. A missing map key gives null, and the checker makes you handle it.

this is lexical and always the object

Inside a method, this is the instance. It cannot be rebound, lost in a callback, or shadowed by an arrow function.

It compiles to a binary

There is no bundler and no runtime to ship: keal build emits C11 and hands it to a C compiler.