# Types as Values

### Types as Values

In Zig, a type is a value.

This is one of the most important ideas behind compile-time programming.

A type can be passed to a function, stored in a constant, compared, and returned from a function.

The special type named `type` represents all types.

```zig
const T: type = i32;
```

Here `T` is a value known at compile time. Its value is the type `i32`.

A function can receive a type parameter:

```zig
fn printType(comptime T: type) void {
    std.debug.print("{s}\n", .{@typeName(T)});
}
```

Call it like this:

```zig
printType(i32);
printType(bool);
printType(f64);
```

The output is:

```text
i32
bool
f64
```

The parameter:

```zig
comptime T: type
```

means:

* `T` is known during compilation
* the value stored in `T` is itself a type

This allows functions to work with types directly.

A function may also return a type.

```zig
fn IntArray(comptime N: usize) type {
    return [N]i32;
}
```

The call:

```zig
const A = IntArray(4);
```

makes `A` equal to:

```zig
[4]i32
```

So this declaration:

```zig
var data: A = .{ 1, 2, 3, 4 };
```

is the same as:

```zig
var data: [4]i32 = .{ 1, 2, 3, 4 };
```

The function constructed a type during compilation.

This idea appears throughout Zig.

A generic container is usually a function returning a type.

```zig
fn Pair(comptime T: type) type {
    return struct {
        first: T,
        second: T,
    };
}
```

Use it like this:

```zig
const IntPair = Pair(i32);

var p = IntPair{
    .first = 10,
    .second = 20,
};
```

The compiler creates a struct where both fields are `i32`.

Another call:

```zig
const FloatPair = Pair(f64);
```

creates a different type.

The language does not need a separate template system for this.

Types are ordinary compile-time values.

This also means types can participate in control flow.

```zig
fn choose(comptime flag: bool) type {
    if (flag)
        return i32;

    return f64;
}
```

Then:

```zig
const A = choose(true);
const B = choose(false);
```

makes:

```zig
A == i32
B == f64
```

A type may be inspected with builtin functions.

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

pub fn main() void {
    std.debug.print("{d}\n", .{@sizeOf(i32)});
    std.debug.print("{d}\n", .{@alignOf(f64)});
}
```

Typical output:

```text
4
8
```

`@sizeOf` and `@alignOf` operate on type values.

Zig also allows reflection on types.

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

fn describe(comptime T: type) void {
    switch (@typeInfo(T)) {
        .int => std.debug.print("integer\n", .{}),
        .float => std.debug.print("float\n", .{}),
        .bool => std.debug.print("boolean\n", .{}),
        else => std.debug.print("other\n", .{}),
    }
}

pub fn main() void {
    describe(i32);
    describe(f64);
    describe(bool);
}
```

The output is:

```text
integer
float
boolean
```

`@typeInfo` returns structural information about a type.

This allows programs to generate specialized behavior during compilation.

For example, a formatting function might handle integers differently from floating-point values.

Because types are values, Zig generic code tends to remain compact.

This function swaps two values:

```zig
fn swap(comptime T: type, a: *T, b: *T) void {
    const tmp = a.*;
    a.* = b.*;
    b.* = tmp;
}
```

The same function works for many types.

```zig
var x: i32 = 10;
var y: i32 = 20;

swap(i32, &x, &y);
```

Or:

```zig
var a: bool = true;
var b: bool = false;

swap(bool, &a, &b);
```

The compiler generates code specialized for each type.

Types as values also make APIs explicit.

Instead of hidden compiler rules or implicit template deduction, the type appears directly in the call:

```zig
swap(i32, &x, &y)
```

The reader can see immediately which type is being used.

This style matches Zig's general design: explicit operations, visible control flow, and minimal hidden behavior.

Exercise 10-9. Write a function `Array(comptime T: type, comptime N: usize) type` returning `[N]T`.

Exercise 10-10. Write a generic `reverse` function for arrays of any type.

Exercise 10-11. Use `@sizeOf` and `@alignOf` to print information about several types.

Exercise 10-12. Write a function `isInteger(comptime T: type) bool` using `@typeInfo`.

