Safer Code
Ban var, enforce immutability. Zero runtime cost.
/#
## var Is Dead
JavaScript's `var` is a footgun:
- Hoists to function scope (not block scope)
- Allows accidental redeclaration
- Leaks out of `for` loops
In native TJS, `var` is a compile error by default — no directive needed.
`const` and `let` work normally.
## const! — Compile-Time Immutability
`const!` declares a binding whose properties can't be mutated.
Unlike `Object.freeze()`, there's **zero runtime cost** —
the check happens at transpile time. The output is plain `const`.
const! config = { debug: false, port: 8080 }
console.log(config.port) // OK — reads are fine
config.debug = true // ERROR at transpile time
const! items = [1, 2, 3]
items.map(x => x * 2) // OK — non-mutating methods
items.push(4) // ERROR — mutating method
When runtimes support records/tuples, `const!` can emit those.
Until then, the semantics are locked in with zero overhead.
#/
// --- const and let work fine ---
const greeting = 'Hello'
let count = 0
count += 1
// --- const! prevents mutation ---
const! config = { debug: false, port: 8080, host: 'localhost' }
// Reads are fine
console.log('port:', config.port)
console.log('host:', config.host)
// --- const! arrays ---
const! colors = ['red', 'green', 'blue']
// Non-mutating methods work
const upper = colors.map(c => c.toUpperCase())
console.log('uppercase:', upper)
const found = colors.find(c => c === 'green')
console.log('found:', found)
// --- Multiple bindings ---
const! settings = { theme: 'dark', fontSize: 14 }
const mutable = { x: 1 }
mutable.x = 2 // Fine — not const!
console.log('settings.theme:', settings.theme)
console.log('mutable.x:', mutable.x)
test 'const! emits as plain const' {
// The output JS has no freeze/seal — zero runtime cost
expect(typeof config).toBe('object')
expect(config.port).toBe(8080)
}
test 'non-mutating methods work on const!' {
expect(colors.map(c => c[0])).toEqual(['r', 'g', 'b'])
expect(colors.filter(c => c !== 'red')).toEqual(['green', 'blue'])
}