# Type Inference

### Type Inference

A declaration may name its type explicitly.

```zig
const n: i32 = 10;
```

The part after the colon is the type:

```zig
i32
```

A declaration may also leave the type out.

```zig
const n = 10;
```

In this case, Zig infers the type from the value and the surrounding context.

Type inference removes repetition. It does not remove types. Every value still has a type.

```zig
const std = @import("std");

pub fn main() void {
    const a: i32 = 10;
    const b = a + 20;

    std.debug.print("{d}\n", .{b});
}
```

Here `a` is an `i32`. The value `20` is used with an `i32`, so `b` is also an `i32`.

Inference often works best for local names.

```zig
const width = 80;
const height = 25;
const area = width * height;
```

The code is clear without repeating the type.

Explicit types are better when the exact representation matters.

```zig
const byte: u8 = 255;
const index: usize = 0;
const offset: i64 = -12;
```

These declarations say more than the values alone.

A function parameter always needs a type.

```zig
fn square(n: i32) i32 {
    return n * n;
}
```

The return type is also written explicitly.

```zig
fn square(n: i32) i32
```

Zig does not infer function parameter types from calls. The function declaration is the contract.

Sometimes a literal has no final type until context gives it one.

```zig
const a: i32 = 10;
const b: u8 = 10;
const c: f64 = 10;
```

The literal `10` can be used in several types, provided the value fits.

This is valid:

```zig
const x: u8 = 255;
```

This is not:

```zig
const x: u8 = 256; // error
```

The value does not fit in `u8`.

An inferred type may be more specific than expected.

```zig
const x = @as(u8, 10);
```

Here `x` is a `u8`, because the expression has type `u8`.

Arrays infer their length and element type.

```zig
const data = [_]u8{ 1, 2, 3 };
```

The type is:

```zig
[3]u8
```

The underscore asks the compiler to count the elements.

For a slice, write the slice type.

```zig
const data: []const u8 = "hello";
```

This says `data` is a slice of constant bytes.

Without the explicit slice type, the string literal keeps its more exact array-pointer type.

```zig
const data = "hello";
```

This is often fine, but sometimes the explicit slice type is clearer.

Inference also works with structs.

```zig
const Point = struct {
    x: i32,
    y: i32,
};

const p = Point{ .x = 3, .y = 4 };
```

The value on the right is a `Point`, so `p` is a `Point`.

Inside a struct literal, field names make the code explicit.

```zig
Point{ .x = 3, .y = 4 }
```

The compiler knows which type is being built from context.

```zig
const p: Point = .{ .x = 3, .y = 4 };
```

Here the type is written on the left, so the right side can use the shorter form.

Use inference when it makes the code shorter without hiding important information.

```zig
const len = buffer.len;
const first = buffer[0];
```

Use explicit types when they are part of the meaning.

```zig
const max_packet_size: u16 = 1500;
var pos: usize = 0;
```

A good rule is simple: write the type when the reader needs it. Leave it out when the expression already says enough.

Exercises:

1. Declare `const n = 10;`, then use it in an expression with an explicit `i32`.

2. Declare a `u8` value using an explicit type. Try a value that is too large.

3. Create an array with `[_]u8{ ... }` and check its length.

4. Define a `Point` struct and create a value using full syntax.

5. Create the same `Point` value using type context and the shorter `.{ ... }` syntax.

