Do you need to specify a type for class variables?

Do I need to give class variables a type?

The documentation is giving me mixed results, according to here, “Their type is inferred using the global type inference algorithm.”, but here it says that “For this reason, Crystal needs to know, in an obvious way (as obvious as to a human), the types of instance and class variables.”.

The following code fails:

class Foo
class_getter bar
class_setter bar
end = 17

with this error:

There was a problem expanding macro ‘class_setter’

Code in

3 | class_setter bar
Called macro defined in macro ‘macro_139766650253984’

1422 | macro class_setter(*names)

Which expanded to:

1 |
2 |
3 | def
Error: can’t infer the type of class variable ‘@@bar’ of Foo

Could you add a type annotation like this

class Foo
  @@bar : Type

replacing Type with the expected type of @@bar?

So I presume the first documentation link is incorrect or I am misunderstanding it, and class variables do need to have a type. Alternatively, maybe I’m doing something wrong and there’s a way to not need to specify a type.

Class and instance variables always need to be typed.

Often, type inference can determine the type without explicit declaration.
But type inference can only work if you directly assign a value (class_getter bar = 17).
class_getter bar does not assign a value, so the compiler has nothing to go by to infer the type.
Even with a value, it sometimes doesn’t work when the resulting type is not directly obvious.

The compiler will ask you to type the variable if it cannot figure it out.
So you can just go by whether the compiler accepts it or not.

As a practical advise, it’s often helpful to add type annotations, even when they’re not required. It helps documenting the code.

This statement is not necessarily wrong, but it’s incomplete and apparently leads to misunderstanding. Type inference can only work if there’s a value from which to infer the type alongside the declaration.

1 Like

I’m proposing a change to improve the documentation: