doc 2 of 2

Typed GDScript — the house contract

These rules apply to every line of GDScript in the projects on this site — the curricula link here rather than restating them — and they are worth adopting in yours.

The six rules#

  1. Every variable is typedvar speed: float = 90.0 — or type-inferred only when the right side makes the type obvious: var direction := Vector2.ZERO.
  2. Every function is fully typed, including -> void: func till(cell: Vector2i) -> bool:
  3. Typed containers: Array[int], Array[Texture2D], Dictionary[Vector2i, PlotState] (typed dictionaries need Godot 4.4+). An untyped Array is a bug you haven't met yet.
  4. Enums over strings for any closed set of values: enum State { IDLE, WALK, USE_TOOL }. A typo'd string fails silently at runtime; a typo'd enum fails at parse time.
  5. Warnings turned up: Project Settings → debug/gdscript/warnings/untyped_declarationWarn. The editor becomes the enforcement; a stage/feature isn't done while the panel shows warnings.
  6. @export with types so the Inspector constrains what can be assigned: @export var data: CropData.

Why (the one-paragraph version)#

Typed GDScript catches whole bug classes at parse time, unlocks precise autocomplete, and runs faster (typed opcodes) — but the speed is a bonus, not the reason. The reason is that types are statements of intent the editor can check while you're learning: every warning is a misconception surfacing early, at the cheapest possible moment.

The traps the contract prevents#

TrapUntyped symptomTyped behavior
Stringly-typed channelsjudged.emit("prefect") scores nothing, silentlyenum member typo won't parse
Variant driftan Array of mixed junk works until it doesn'tArray[NoteData] rejects at assignment
Wrong-space vectorsVector2 where Vector2i cell math expected — off-by-subpixel bugssignature mismatch flagged in-editor
Silent null flowcrash three calls away from the causetyped returns force the null question at the boundary

Docs: Static typing in GDScript