Reflection and Type Introspection

26.1 @typeInfo and @Type

std.builtin.Type tags: .int, .float, .pointer, .array, .@"struct", .@"enum", .@"union", .optional, .error_union, .error_set, .@"fn", .vector, .@"opaque", .bool, .void, .type, .comptime_int, ... (lowercase since 0.14).

const User = struct {
    name: []const u8,
    age: u32,
    active: bool = true,
};

fn printFields(comptime T: type) void {
    const info = @typeInfo(T);
    switch (info) {
        .@"struct" => |s| {
            inline for (s.fields) |field| {
                std.debug.print("{s}: {s}\n", .{ field.name, @typeName(field.type) });
            }
        },
        else => @compileError("not a struct"),
    }
}

fn dumpValue(value: anytype) void {
    inline for (std.meta.fields(@TypeOf(value))) |f| {
        std.debug.print("{s} = {any}\n", .{ f.name, @field(value, f.name) });   // dynamic field access
    }
}

26.2 Constructing Types with @Type

fn MakeOptionalFields(comptime T: type) type {
    const fields = std.meta.fields(T);
    var new_fields: [fields.len]std.builtin.Type.StructField = undefined;
    for (fields, 0..) |f, i| {
        new_fields[i] = .{
            .name = f.name,
            .type = ?f.type,
            .default_value_ptr = &@as(?f.type, null),
            .is_comptime = false,
            .alignment = @alignOf(?f.type),
        };
    }
    return @Type(.{ .@"struct" = .{
        .layout = .auto,
        .fields = &new_fields,
        .decls = &.{},
        .is_tuple = false,
    } });
}
const PartialUser = MakeOptionalFields(User);   // every field optional (like TypeScript's Partial)

26.3 Reflection Helpers

Builtin / std.meta Type of an expression Type name string @hasField(T, "name"), @hasDecl(T, "name") @field(obj, "name") Access a field by comptime string @FieldType(T, "name") Type of a field (0.14+) Tag as a string

@sizeOf, @alignOf, @bitSizeOf, @offsetOf, @bitOffsetOf

std.meta.fields, std.meta.declarations, std.meta.Tag, std.meta.FieldEnum, std.meta.eql, std.meta.activeTag, std.meta.stringToEnum, std.meta.Child, std.meta.Elem, std.meta.hasFn

Practical uses: serializers (JSON, ZON), ORMs, CLI argument parsers generated from structs, ECS (entity component systems), bindings generators.