Variables
Variables
let introduces a binding. There are three forms.
let count: number = 0 // explicit type with a value
let count = 0 // type inferred from the value
let count: number // typed, no value yetReassignment uses the name alone:
count = count + 1Inference
let x = value takes the type from the initializer, so the annotation is
optional wherever the value already says what the type is:
let names = new Array<string>()
let total = 0
let ready = names.size() > 0Annotating anyway is still useful when the initializer does not read clearly, or when you want the declaration to state intent rather than repeat a call.
A typed declaration may omit the initializer, which declares the name and leaves it uninitialized until an assignment reaches it. The analyzer tracks that and reports a read before the first assignment.
Globals always need a type
Inference is a local-scope feature. A declaration at module scope has to state its type:
let WORKSPACE_ROOT: string = resolve_workspace_root()Leaving the type off a global is an error: global variable declarations must include an explicit type, because inference is only available for locals.
Destructuring
let (a, b) = pair binds each name to a positional element of the value. The
first name takes get_first, the second get_second, and the element types are
inferred from those accessors:
let (key, value) = entryThe same pattern works in a for loop. See the loops page.
Fields
Class fields are declared without let, inside the class body:
class Counter {
count: i64
label: string
}Fields carry no let and no inference: a field always states its type.
Scope
A binding is visible from its declaration to the end of the enclosing block. Blocks nest, and an inner block can shadow a name from an outer one.