Skip to main content

Type Inference

If a variable or constant declaration is not annotated explicitly with a type, the declaration's type is inferred from the initial value.

Basic Literals

Decimal integer literals and hex literals are inferred to type Int.


_10
let a = 1
_10
// `a` has type `Int`
_10
_10
let b = -45
_10
// `b` has type `Int`
_10
_10
let c = 0x02
_10
// `c` has type `Int`

Unsigned fixed-point literals are inferred to type UFix64. Signed fixed-point literals are inferred to type Fix64.


_10
let a = 1.2
_10
// `a` has type `UFix64`
_10
_10
let b = -1.2
_10
// `b` has type `Fix64`

Similarly, for other basic literals, the types are inferred in the following manner:

Literal KindExampleInferred Type (x)
String literallet x = "hello"String
Boolean literallet x = trueBool
Nil literallet x = nilNever?

Array Literals

Array literals are inferred based on the elements of the literal, and to be variable-size. The inferred element type is the least common super-type of all elements.


_14
let integers = [1, 2]
_14
// `integers` has type `[Int]`
_14
_14
let int8Array = [Int8(1), Int8(2)]
_14
// `int8Array` has type `[Int8]`
_14
_14
let mixedIntegers = [UInt(65), 6, 275, Int128(13423)]
_14
// `mixedIntegers` has type `[Integer]`
_14
_14
let nilableIntegers = [1, nil, 2, 3, nil]
_14
// `nilableIntegers` has type `[Int?]`
_14
_14
let mixed = [1, true, 2, false]
_14
// `mixed` has type `[AnyStruct]`

Dictionary Literals

Dictionary literals are inferred based on the keys and values of the literal. The inferred type of keys and values is the least common super-type of all keys and values, respectively.


_20
let booleans = {
_20
1: true,
_20
2: false
_20
}
_20
// `booleans` has type `{Int: Bool}`
_20
_20
let mixed = {
_20
Int8(1): true,
_20
Int64(2): "hello"
_20
}
_20
// `mixed` has type `{Integer: AnyStruct}`
_20
_20
// Invalid: mixed keys
_20
//
_20
let invalidMixed = {
_20
1: true,
_20
false: 2
_20
}
_20
// The least common super-type of the keys is `AnyStruct`.
_20
// But it is not a valid type for dictionary keys.

Ternary Expression

Ternary expression type is inferred to be the least common super-type of the second and third operands.


_10
let a = true ? 1 : 2
_10
// `a` has type `Int`
_10
_10
let b = true ? 1 : nil
_10
// `b` has type `Int?`
_10
_10
let c = true ? 5 : (false ? "hello" : nil)
_10
// `c` has type `AnyStruct`

Functions

Functions are inferred based on the parameter types and the return type.


_10
let add = (a: Int8, b: Int8): Int {
_10
return a + b
_10
}
_10
_10
// `add` has type `((Int8, Int8): Int)`

Type inference is performed for each expression / statement, and not across statements.

Ambiguities

There are cases where types cannot be inferred. In these cases explicit type annotations are required.


_10
// Invalid: not possible to infer type based on array literal's elements.
_10
//
_10
let array = []
_10
_10
// Instead, specify the array type and the concrete element type, e.g. `Int`.
_10
//
_10
let array: [Int] = []
_10
_10
// Or, use a simple-cast to annotate the expression with a type.
_10
let array = [] as [Int]


_11
// Invalid: not possible to infer type based on dictionary literal's keys and values.
_11
//
_11
let dictionary = {}
_11
_11
// Instead, specify the dictionary type and the concrete key
_11
// and value types, e.g. `String` and `Int`.
_11
//
_11
let dictionary: {String: Int} = {}
_11
_11
// Or, use a simple-cast to annotate the expression with a type.
_11
let dictionary = {} as {String: Int}