You should almost never annotate the type of a private field or a localvariable, as their type will usually be immediately evident intheir value:

However, you may wish to still display the type where the assigned value has acomplex or non-obvious form.

All public methods should have explicit type annotations. Type inference maybreak encapsulation in these cases, because it depends on internal methodand class details. Without an explicit type, a change to the internalsof a method or val could alter the public API of the class without warning,potentially breaking client code. Explicit type annotations can also helpto improve compile times.

Function values support a special case of type inference which is worthcalling out on its own:

  1. ls map (str => str.toInt)

In cases where Scala already knows the type of the function value we aredeclaring, there is no need to annotate the parameters (in this case,str). This is an intensely helpful inference and should be preferredwhenever possible. Note that implicit conversions which operate onfunction values will nullify this inference, forcing the explicitannotation of parameter types.

Type annotations should be patterned according to the followingtemplate:

    This is actually valid Scala, declaring a value to be of type ::.Obviously, the prefix-style annotation colon muddles things greatly.

    Type ascription is often confused with type annotation, as the syntax inScala is identical. The following are examples of ascription:

    • Nil: List[String]
    • Set(values: _*)
    • "Daniel": AnyRef

    Ascription is basically just an up-cast performed at compile-time forthe sake of the type checker. Its use is not common, but it does happenon occasion. The most often seen case of ascription is invoking avarargs method with a single Seq parameter. This is done by ascribingthe type (as in the second example above).

    Ascription follows the type annotation conventions; a space follows thecolon.

    Function types should be declared with a space between the parametertype, the arrow and the return type:

    1. def foo(f: Int => String) = ...
    2. def bar(f: (Boolean, Double) => List[String]) = ...

    Parentheses should be omitted wherever possible (e.g. methods ofarity-1, such as Int => String).

    Arity-1

    1. def map[B](f: A => B) = ...

    Specifically, the parentheses may be omitted from the parameter type.Thus, we did not declare f to be of type (A) => B, as this wouldhave been needlessly verbose. Consider the more extreme example:

    By omitting the parentheses, we have saved six whole characters anddramatically improved the readability of the type expression.

    Structural types should be declared on a single line if they are lessthan 50 characters in length. Otherwise, they should be split acrossmultiple lines and (usually) assigned to their own type alias:

    1. // wrong!
    2. // right!
    3. private type FooParam = {
    4. val baz: List[String => String]
    5. def bar(a: Int, b: Int): String
    6. }
    7. def foo(a: FooParam) = ...

    Simpler structural types (under 50 characters) may be declared and usedinline:

      When declaring structural types inline, each member should be separatedby a semi-colon and a single space, the opening brace should befollowed by a space while the closing brace should be preceded by aspace (as demonstrated in both examples above).

      Structural types are implemented with reflection at runtime, and areinherently less performant than nominal types. Developers shouldprefer the use of nominal types, unless structural types provide aclear benefit.