Constructors define how class values are initialized.
A constructor is written with the constructor keyword followed by a parameter list and body.
💡 User (
name is string
constructor(name is string) (
this.name = name
)
)
constructor(...) (...) is the only constructor spelling.
Constructors may appear in reference classes and primitive classes. Extension classes cannot define constructors.
Calling Classes
Calling a class creates an instance value. Typical does not use a new keyword.
user = User("Ada")
When an expression names a class, a call to that expression is a construction call. Static members do not conflict with construction.
If a class does not declare a constructor, it receives an implicit empty constructor. The editor may hide this constructor.
Constructor overloading is not supported. A class may have one synchronous constructor or one async constructor. Default and optional parameters are used for construction APIs that need multiple call shapes.
Visibility
A constructor inherits the visibility and constructability of its containing class unless the constructor is listed in a visibility group.
💡 User (
constructor(name is string) (
this.name = name
)
export (
constructor
)
)
Constructors are referenced as constructor in visibility groups.
Field Initialization
Every stored field must be definitely assigned by the end of construction.
Field initializers count as assignments before the constructor body runs.
💡 User (
active is bool = true
name is string
constructor(name is string) (
this.name = name
)
)
A field type may be inferred from a definite constructor assignment.
💡 User (
name
constructor(name is string) (
this.name = name
)
)
If a stored field is not definitely assigned by the end of construction, the compiler generates a notice and provides a default value.
Constructors do not return values.
Parameter Promotion
Constructor parameters may be promoted to stored properties by listing the parameter name in a visibility group.
💡 User (
constructor(name is string, id is string) (
)
export (
constructor
name
)
exclude (
id
)
)
In this example, name becomes an exported property and id becomes a private promoted property.
When a visibility group entry inside a class matches an existing class member, the visibility applies to that member. If no matching class member exists, Typical looks for a matching constructor parameter and promotes it.
A promoted constructor parameter cannot also be declared as a separate field or property in the same class.
Super Calls
When a class inherits from a parent class with a constructor, the child constructor must call super(...).
💡 Animal (
constructor(name is string) (
this.name = name
)
)
💡 Bunny is Animal (
constructor(name is string) (
super(name)
)
)
The editor inserts required super(...) calls automatically. These calls are fixed tokens: they may be moved up or down, but they cannot be deleted.
this is lexically unavailable until all required superclass constructor calls have completed.
Multiple Inheritance
Classes with multiple parents call one superclass constructor per parent.
💡 Bunny is Animal, Pet (
constructor(name is string) (
super(name)
super()
)
)
Required super(...) calls appear together as a block. Parent order determines the default constructor call order, and the editor enforces this order unless the author reorders the calls as a block.
If inherited constructors require incompatible initialization, the compiler generates a notice.
Async Constructors
A constructor may be marked async.
async getAsyncValue() (
return 456
)
💡 Foo (
async constructor(initialValue is int) (
this.bar = initialValue
this.baz = await getAsyncValue()
)
bar is int
baz is int
)
async main() (
foo = await Foo(123)
)
Calling a class with an async constructor produces a promise that resolves to the constructed class value.
Async constructors may use await, parameter promotion, field assignment, and inherited constructor behavior. An async constructor may be inherited.
Inside an async constructor, this follows the normal superclass initialization rule. After required superclass constructor calls have completed, this may be used before awaited initialization has completed.
For TypeScript output, an async constructor lowers to a static async new() method. This mirrors the normal TypeScript factory idiom while preserving Typical constructor syntax and parameter promotion.
class Foo
{
static async new(initialValue: number): Promise<Foo>
{
const value = new Foo();
value.bar = initialValue;
value.baz = await getAsyncValue();
return value;
}
}
A class with an async constructor cannot define its own static method named new.
Rust output lowers async construction to an async associated construction function. The selected Rust backend chooses the async runtime.
Static Constructors
A class may define a static constructor.
Static constructors run automatically the first time an instance is constructed or a static member is accessed. They run at most once.
💡 Registry (
static (
items is Array<string> = []
constructor() (
items.push("ready")
)
)
)
Static constructors are used for one-time class initialization. They are not called directly.