ZigAdvanced

Zig Reflection: The @typeInfo Guide

TT
TopicTrick Team
Zig Reflection: The @typeInfo Guide

Zig Reflection: The @typeInfo Guide

In C++, discovering the names or types of fields in a struct is impossible without complex external parsing tools. In Java or C#, reaching into a class requires "Slow Reflection" that forces the CPU to perform heavy string lookups and dynamic jumps at runtime, destroying performance.

Zig introduces a revolutionary concept: Static Reflection. During the build process, the compiler grants you "X-ray Vision" into every type, struct, and function in your codebase via @typeInfo. This 1,500+ word guide explores how to build "Self-Aware" architecture—code that reads its own metadata to automate JSON serialization, CLI generation, and ORM mapping with zero runtime overhead.


1. What is @typeInfo? (The Type's Soul)

@typeInfo(T) returns a Tagged Union (specifically std.builtin.Type) that describes the internal structure of the type T.

  • If T is an Integer, the metadata reveals its bit-width and signedness.
  • If T is a Struct, the metadata reveals every field, its memory offset, and even its default value.

Decoding a Struct

zig

2. The Physics of Introspection: The Metadata Table

How does Zig store the "Soul" of a type? It uses the Compile-Time Metadata Table.

The Introspection Mirror

  • The Concept: Every type in your Zig program has a corresponding entry in the compiler's internal state.
  • The Physics: When you call @typeInfo(T), you aren't running a function; you are accessing a Look-Up Table (LUT) that exists inside the compiler's RAM.
  • The Result: This metadata is "Static." It costs zero bytes in your final binary unless you explicitly decide to store it there. You have the power of a "Managed Language" (like C#) without the "Runtime Metadata" overhead that bloats memory usage.

3. Using @field: Accessing Data by Name

Reflection is useless if you can't act on it. The @field(obj, name) built-in bridge the gap between "Strings" and "Code." It allows you to read or write to a field using its name as a string.

The Universal Serializer Pattern

zig

Performance Note: In other languages, this loop would be slow. In Zig, because we use inline for, the compiler unrolls this loop at build-time. The final machine code is exactly as fast as if you had hard-coded std.debug.print("id = {d}", .{obj.id}).


4. Reification Physics: Turning Data into Silicon Logic

If @typeInfo is "Reading," then @Type is "Writing."

The Reification Mirror

  • The Process: Reification is the act of taking a piece of data (a struct description) and asking the compiler to "Build me this into a physical memory layout."
  • The Physics: The compiler takes your std.builtin.Type description and runs it through the Layout Engine. It calculates bit-offsets, padding, and alignment for a brand new type.
  • The Result: This allows you to build "Dynamic-Static" systems. You can read a JSON file at comptime and generate a perfectly optimized Zig struct that matches the JSON schema EXACTLY. No maps, no string-lookups—just raw field access.

5. The "Self-Driving" CLI Patterns

This is the most advanced concept in Zig metaprogramming. If @typeInfo turns a Type into Metadata, then @Type (the inverse) turns Metadata back into a Type.

Example: The "Update DTO" Generator

Imagine you have a User struct, but you want to create an UpdateUser struct where every field is Optional (?) so the user can update only the fields they want.

zig

With this pattern, your database schema and your network objects are always in sync. If you add a field to User, the UpdateUser struct updates itself automatically.


4. The "Self-Driving" CLI Patterns

You can use reflection to analyze a struct and automatically generate a Command Line Interface.

  • You pull the field names to create --flags.
  • You use the types to validate input (ensure --id is a number).
  • You use @hasDecl to check if a struct has a help() function to display documentation.

This is how professional Zig tools maintain high feature-velocity with minimal boilerplate code.


5. Reflection is the "Automation Layer" of your architecture. By mastering the ability to read and write code metadata, you gain the ability to build systems that are "Self-Aware" and magically flexible. You graduate from "Writing code for every type" to "Architecting Code Generators."


Phase 13: Reflection Mastery Checklist

  • Audit your serialization logic: Can you automate a JSON or CSV generator using @typeInfo and inline for?
  • Implement Universal Mapping: Use @field to build a function that clones data between two similar structs.
  • Build a Reified Type: Use the @Type built-in to generate a "Shadow Struct" (e.g., all fields optional) from an existing type.
  • Setup Meta-Validation: Use reflection to verify that a struct has a specific "Magic Number" field or a required alignment.
  • Profile your Compile Times: While reflection is zero-cost at runtime, verify that deep nested reflection doesn't blow out your build times on large modules.

Read next: Zig Allocators: The Art of Memory Sovereignty →


Part of the Zig Mastery Course — engineering the vision.