Exports and annotations
GDScript annotations (@export_range, @onready, @tool, …) are TypeScript decorators with the same names. The one exception is @export itself, which you write as @exports.
@tool@icon('res://icons/turret.svg')export class Turret extends Node2D { @export_group('Combat') @exports damage: int = 10; @export_range(0.1, 5.0, 0.1) fire_rate: float = 1.0; @export_enum('Bullet', 'Laser', 'Rocket') ammo: int = 0;
@export_group('Scene') @exports bullet_scene!: PackedScene; @exports target: Node2D | null = null; @export_multiline() notes: string = '';
@onready muzzle = gd.as(this.get_node('Muzzle'), Marker2D);}@tool@icon("res://icons/turret.svg")class_name Turretextends Node2D
@export_group("Combat")@exportvar damage: int = 10@export_range(0.1, 5.0, 0.1)var fire_rate: float = 1.0@export_enum("Bullet", "Laser", "Rocket")var ammo: int = 0@export_group("Scene")@exportvar bullet_scene: PackedScene@exportvar target: Node2D = null@export_multilinevar notes: String = ""@onreadyvar muzzle = self.get_node("Muzzle") as Marker2DEvery annotation Godot knows is available, with its arguments checked by TypeScript. Each one goes on its own line in the .gd, right above what it annotates.
Why @exports
Section titled “Why @exports”export is a reserved word in TypeScript, so @export doesn’t even parse. Write @exports, plural; it goes out as @export. All other annotations keep their Godot names: @export_range, @export_file, @export_group and so on.
Note: An annotation whose arguments are all optional needs empty parentheses when you pass none:
@export_multiline(),@export_file(),@rpc(). Without them TypeScript reports an error about the decorator’s return type. The.gdgets the bare@export_multiline. Annotations that never take arguments, such as@exports,@onreadyand@tool, are written without parentheses.
Exports without a default
Section titled “Exports without a default”An export the inspector fills in, like bullet_scene above, needs no value in the code: mark it with !, or use | null = null when it may be left empty, as Variables and types explains.
@onready
Section titled “@onready”@onready works as in GDScript: the initializer runs just before _ready(), when the child nodes exist. With scene typings, this.get_node() already has the right type, so you can write @onready sprite: Sprite2D = this.get_node('Sprite2D');. Without them, cast the node with gd.as as above.
Class annotations
Section titled “Class annotations”@tool, @icon(...) and @static_unload go above the class, and come out above class_name. You don’t need @abstract: an abstract class gets it automatically (see Scripts and classes).
Method and statement annotations
Section titled “Method and statement annotations”Annotations such as @rpc and @warning_ignore work on methods too:
export class Lobby extends Node { @rpc('any_peer', 'call_local') ping(from: int) { print('ping from ', from); }
@warning_ignore('unused_parameter') _process(delta: float) { print('tick'); }}class_name Lobbyextends Node
@rpc("any_peer", "call_local")func ping(from: int): print("ping from ", from)
@warning_ignore("unused_parameter")func _process(delta: float): print("tick")A decorator can’t go on a statement inside a function; there you write the annotation in a // @gd.eval: comment, as Escape hatches shows.
Details
Section titled “Details”See decorators and annotations in the reference, and gd.eval for the magic comment.
