static_typing.rst 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. .. _doc_gdscript_static_typing:
  2. Static typing in GDScript
  3. =========================
  4. In this guide, you will learn:
  5. - **How to use types in GDScript**
  6. - That **static types can help you avoid bugs**
  7. Where and how you use this new language feature is entirely up to you:
  8. you can use it only in some sensitive GDScript files, use it everywhere,
  9. or write code like you always did!
  10. Static types can be used on variables, constants, functions, parameters,
  11. and return types.
  12. A brief look at static typing
  13. -----------------------------
  14. With typed GDScript, Godot can detect even more errors as you write
  15. code! It gives you and your teammates more information as you're
  16. working, as the arguments' types show up when you call a method.
  17. Imagine you're programming an inventory system. You code an ``Item``
  18. node, then an ``Inventory``. To add items to the inventory, the people
  19. who work with your code should always pass an ``Item`` to the
  20. ``Inventory.add`` method. With types, you can enforce this:
  21. ::
  22. # In 'item.gd'.
  23. class_name Item
  24. # In 'inventory.gd'.
  25. class_name Inventory
  26. func add(reference: Item, amount: int = 1):
  27. var item = find_item(reference)
  28. if not item:
  29. item = _instance_item_from_db(reference)
  30. item.amount += amount
  31. Another significant advantage of typed GDScript is the new **warning
  32. system**. From version 3.1, Godot gives you warnings about your code as
  33. you write it: the engine identifies sections of your code that may lead
  34. to issues at runtime, but lets you decide whether or not you want to
  35. leave the code as it is. More on that in a moment.
  36. Static types also give you better code completion options. Below, you
  37. can see the difference between a dynamic and a static typed completion
  38. options for a class called ``PlayerController``.
  39. You've probably stored a node in a variable before, and typed a dot to
  40. be left with no autocomplete suggestions:
  41. .. figure:: img/typed_gdscript_code_completion_dynamic.webp
  42. :alt: code completion options for dynamic
  43. This is due to dynamic code. Godot cannot know what node or value type
  44. you're passing to the function. If you write the type explicitly
  45. however, you will get all public methods and variables from the node:
  46. .. figure:: img/typed_gdscript_code_completion_typed.webp
  47. :alt: code completion options for typed
  48. In the future, typed GDScript will also increase code performance:
  49. Just-In-Time compilation and other compiler improvements are already
  50. on the roadmap!
  51. Overall, typed programming gives you a more structured experience. It
  52. helps prevent errors and improves the self-documenting aspect of your
  53. scripts. This is especially helpful when you're working in a team or on
  54. a long-term project: studies have shown that developers spend most of
  55. their time reading other people's code, or scripts they wrote in the
  56. past and forgot about. The clearer and the more structured the code, the
  57. faster it is to understand, the faster you can move forward.
  58. How to use static typing
  59. ------------------------
  60. To define the type of a variable or a constant, write a colon after the
  61. variable's name, followed by its type. E.g. ``var health: int``. This
  62. forces the variable's type to always stay the same:
  63. ::
  64. var damage: float = 10.5
  65. const MOVE_SPEED: float = 50.0
  66. Godot will try to infer types if you write a colon, but you omit the
  67. type:
  68. ::
  69. var life_points := 4
  70. var damage := 10.5
  71. var motion := Vector2()
  72. Currently you can use three types of… types:
  73. 1. :ref:`Built-in <doc_gdscript_builtin_types>`
  74. 2. Core classes and nodes (``Object``, ``Node``, ``Area2D``,
  75. ``Camera2D``, etc.)
  76. 3. Your own custom classes. Look at the new :ref:`class_name <doc_gdscript_basics_class_name>`
  77. feature to register types in the editor.
  78. .. note::
  79. You don't need to write type hints for constants, as Godot sets it automatically from the assigned value. But you can still do so to make the intent of your code clearer.
  80. Custom variable types
  81. ~~~~~~~~~~~~~~~~~~~~~
  82. You can use any class, including your custom classes, as types. There
  83. are two ways to use them in scripts. The first method is to preload the
  84. script you want to use as a type in a constant:
  85. ::
  86. const Rifle = preload("res://player/weapons/rifle.gd")
  87. var my_rifle: Rifle
  88. The second method is to use the ``class_name`` keyword when you create.
  89. For the example above, your rifle.gd would look like this:
  90. ::
  91. class_name Rifle
  92. extends Node2D
  93. If you use ``class_name``, Godot registers the Rifle type globally in
  94. the editor, and you can use it anywhere, without having to preload it
  95. into a constant:
  96. ::
  97. var my_rifle: Rifle
  98. Variable casting
  99. ~~~~~~~~~~~~~~~~
  100. Type casting is a key concept in typed languages.
  101. Casting is the conversion of a value from one type to another.
  102. Imagine an Enemy in your game, that ``extends Area2D``. You want it to
  103. collide with the Player, a ``CharacterBody2D`` with a script called
  104. ``PlayerController`` attached to it. You use the ``on_body_entered``
  105. signal to detect the collision. With typed code, the body you detect is
  106. going to be a generic ``PhysicsBody2D``, and not your
  107. ``PlayerController`` on the ``_on_body_entered`` callback.
  108. You can check if this ``PhysicsBody2D`` is your Player with the ``as``
  109. casting keyword, and using the colon ``:`` again to force the variable
  110. to use this type. This forces the variable to stick to the
  111. ``PlayerController`` type:
  112. ::
  113. func _on_body_entered(body: PhysicsBody2D) -> void:
  114. var player := body as PlayerController
  115. if not player:
  116. return
  117. player.damage()
  118. As we're dealing with a custom type, if the ``body`` doesn't extend
  119. ``PlayerController``, the ``player``\ variable will be set to ``null``.
  120. We can use this to check if the body is the player or not. We will also
  121. get full autocompletion on the player variable thanks to that cast.
  122. .. note::
  123. If you try to cast with a built-in type and it fails, Godot will throw an error.
  124. .. _doc_gdscript_static_typing_safe_lines:
  125. Safe lines
  126. ^^^^^^^^^^
  127. You can also use casting to ensure safe lines. Safe lines are a new
  128. tool in Godot 3.1 to tell you when ambiguous lines of code are
  129. type-safe. As you can mix and match typed and dynamic code, at times,
  130. Godot doesn't have enough information to know if an instruction will trigger
  131. an error or not at runtime.
  132. This happens when you get a child node. Let's take a timer for example:
  133. with dynamic code, you can get the node with ``$Timer``. GDScript
  134. supports `duck-typing <https://stackoverflow.com/a/4205163/8125343>`__,
  135. so even if your timer is of type ``Timer``, it is also a ``Node`` and an
  136. ``Object``, two classes it extends. With dynamic GDScript, you also
  137. don't care about the node's type as long as it has the methods you need
  138. to call.
  139. You can use casting to tell Godot the type you expect when you get a
  140. node: ``($Timer as Timer)``, ``($Player as CharacterBody2D)``, etc.
  141. Godot will ensure the type works and if so, the line number will turn
  142. green at the left of the script editor.
  143. .. figure:: img/typed_gdscript_safe_unsafe_line.webp
  144. :alt: Unsafe vs Safe Line
  145. Unsafe line (line 7) vs Safe Lines (line 6 and 8)
  146. .. note::
  147. You can turn off safe lines or change their color in the editor settings.
  148. Define the return type of a function with the arrow ->
  149. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  150. To define the return type of a function, write a dash and a right angle
  151. bracket ``->`` after its declaration, followed by the return type:
  152. ::
  153. func _process(delta: float) -> void:
  154. pass
  155. The type ``void`` means the function does not return anything. You can
  156. use any type, as with variables:
  157. ::
  158. func hit(damage: float) -> bool:
  159. health_points -= damage
  160. return health_points <= 0
  161. You can also use your own nodes as return types:
  162. ::
  163. # inventory.gd
  164. # Adds an item to the inventory and returns it.
  165. func add(reference: Item, amount: int) -> Item:
  166. var item: Item = find_item(reference)
  167. if not item:
  168. item = ItemDatabase.get_instance(reference)
  169. item.amount += amount
  170. return item
  171. Define the element type of an Array
  172. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  173. To define the type of an Array, enclose the type name in ``[]``.
  174. An array's type applies to ``for`` loop variables, as well as some operators like ``[]``, ``[]=``, and ``+``.
  175. Array methods (such as ``push_back``) and other operators (such as ``==``) are still untyped.
  176. Primitive types, builtin classes, and custom classes may be used as types.
  177. Nested array types are not supported.
  178. ::
  179. var scores: Array[int] = [10, 20, 30]
  180. var vehicles: Array[Node] = [$Car, $Plane]
  181. var items: Array[Item] = [Item.new()]
  182. # var arrays: Array[Array] -- disallowed
  183. for score in scores:
  184. # score has type `int`
  185. # The following would be errors:
  186. scores += vehicles
  187. var s: String = scores[0]
  188. scores[0] = "lots"
  189. Since Godot 4.2, you can also specify a type for the loop variable in a ``for`` loop.
  190. For instance, you can write:
  191. ::
  192. var names = ["John", "Marta", "Samantha", "Jimmy"]
  193. for name: String in names:
  194. pass
  195. The array will remain untyped, but the ``name`` variable within the ``for`` loop
  196. will always be of String type.
  197. Typed or dynamic: stick to one style
  198. ------------------------------------
  199. Typed GDScript and dynamic GDScript can coexist in the same project. But
  200. it's recommended to stick to either style for consistency in your codebase,
  201. and for your peers. It's easier for everyone to work together if you
  202. follow the same guidelines, and faster to read and understand other
  203. people's code.
  204. Typed code takes a little more writing, but you get the benefits we
  205. discussed above. Here's an example of the same, empty script, in a
  206. dynamic style:
  207. ::
  208. extends Node
  209. func _ready():
  210. pass
  211. func _process(delta):
  212. pass
  213. And with static typing:
  214. ::
  215. extends Node
  216. func _ready() -> void:
  217. pass
  218. func _process(delta: float) -> void:
  219. pass
  220. As you can see, you can also use types with the engine's virtual
  221. methods. Signal callbacks, like any methods, can also use types. Here's
  222. a ``body_entered`` signal in a dynamic style:
  223. ::
  224. func _on_area_2d_body_entered(body):
  225. pass
  226. And the same callback, with type hints:
  227. ::
  228. func _on_area_entered(area: CollisionObject2D) -> void:
  229. pass
  230. You're free to replace, e.g. the ``CollisionObject2D``, with your own type,
  231. to cast parameters automatically:
  232. ::
  233. func _on_area_entered(bullet: Bullet) -> void:
  234. if not bullet:
  235. return
  236. take_damage(bullet.damage)
  237. The ``bullet`` variable could hold any ``CollisionObject2D`` here, but
  238. we make sure it is our ``Bullet``, a node we created for our project. If
  239. it's anything else, like an ``Area2D``, or any node that doesn't extend
  240. ``Bullet``, the ``bullet`` variable will be ``null``.
  241. Warning system
  242. --------------
  243. .. note::
  244. Documentation about the GDScript warning system has been moved to
  245. :ref:`doc_gdscript_warning_system`.
  246. A case where you can't specify types
  247. ------------------------------------
  248. To wrap up this introduction, let's mention a case where you can't
  249. use type hints. This will trigger a **syntax error**.
  250. You can't specify the type of individual members in an array:
  251. ::
  252. var enemies: Array = [$Goblin: Enemy, $Zombie: Enemy]
  253. Summary
  254. -------
  255. Typed GDScript is a powerful tool. It helps you write more structured code,
  256. avoid common errors, and create scalable systems. In the future, static types
  257. will also bring you a nice performance boost thanks to upcoming compiler
  258. optimizations.