---
title: "@typeInfo em Zig — Referência e Exemplos"
url: "https://ziglang.com.br/builtins/@typeinfo-em-zig-refer%C3%AAncia-e-exemplos/"
markdown_url: "https://ziglang.com.br/builtins/@typeinfo-em-zig-refer%C3%AAncia-e-exemplos.MD"
description: "Referência completa do @typeInfo em Zig. Aprenda a inspecionar tipos em tempo de compilação com exemplos práticos em português."
date: "2026-02-21"
author: "Zig Brasil"
---

# @typeInfo em Zig — Referência e Exemplos

Referência completa do @typeInfo em Zig. Aprenda a inspecionar tipos em tempo de compilação com exemplos práticos em português.


# @typeInfo em Zig

O `@typeInfo` é um dos builtins mais poderosos do Zig para metaprogramação. Ele permite inspecionar qualquer tipo em tempo de compilação, retornando uma union detalhada com todas as informações sobre a estrutura daquele tipo. É fundamental para escrever código genérico e bibliotecas que operam sobre tipos arbitrários.

## Sintaxe

```zig
@typeInfo(comptime T: type) std.builtin.Type
```

## O que faz

O `@typeInfo` recebe um tipo como parâmetro e retorna uma instância da union `std.builtin.Type`, que contém informações detalhadas sobre o tipo fornecido. Essa union possui variantes para cada categoria de tipo em Zig: inteiros, floats, ponteiros, arrays, structs, enums, unions, funções, entre outros.

Com essas informações, é possível escrever funções genéricas que se comportam de forma diferente dependendo das propriedades do tipo recebido, implementar serialização automática, validação de tipos e muito mais.

## Parâmetros

- **T** (`type`, comptime): O tipo a ser inspecionado. Deve ser conhecido em tempo de compilação. Pode ser qualquer tipo válido em Zig, incluindo tipos primitivos, structs, enums, unions, ponteiros, arrays e tipos de função.

## Valor de retorno

Retorna uma instância de `std.builtin.Type`, que é uma tagged union com variantes como:

- `.int` — Informações sobre tipos inteiros (bits, sinalização)
- `.float` — Informações sobre tipos de ponto flutuante
- `.pointer` — Informações sobre ponteiros (alinhamento, sentinela, tamanho)
- `.array` — Informações sobre arrays (comprimento, tipo filho)
- `.@"struct"` — Informações sobre structs (campos, declarações)
- `.@"enum"` — Informações sobre enums (campos, tipo de tag)
- `.@"union"` — Informações sobre unions (campos, tipo de tag)
- `.@"fn"` — Informações sobre funções (parâmetros, retorno)
- E muitas outras variantes.

## Exemplos práticos

### Exemplo 1: Verificando a categoria de um tipo

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

fn descreverTipo(comptime T: type) []const u8 {
    const info = @typeInfo(T);
    return switch (info) {
        .int => "tipo inteiro",
        .float => "tipo ponto flutuante",
        .pointer => "tipo ponteiro",
        .array => "tipo array",
        .@"struct" => "tipo struct",
        .@"enum" => "tipo enum",
        .bool => "tipo booleano",
        else => "outro tipo",
    };
}

test "descrever tipos" {
    try std.testing.expectEqualStrings("tipo inteiro", descreverTipo(i32));
    try std.testing.expectEqualStrings("tipo ponto flutuante", descreverTipo(f64));
    try std.testing.expectEqualStrings("tipo booleano", descreverTipo(bool));
}
```

### Exemplo 2: Inspecionando campos de uma struct

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

const Pessoa = struct {
    nome: []const u8,
    idade: u32,
    ativo: bool,
};

fn listarCampos(comptime T: type) void {
    const info = @typeInfo(T);
    switch (info) {
        .@"struct" => |s| {
            inline for (s.fields) |campo| {
                std.debug.print("Campo: {s}, Tipo: {s}\n", .{
                    campo.name,
                    @typeName(campo.type),
                });
            }
        },
        else => @compileError("Esperava uma struct"),
    }
}

test "listar campos de Pessoa" {
    listarCampos(Pessoa);
    // Saída:
    // Campo: nome, Tipo: []const u8
    // Campo: idade, Tipo: u32
    // Campo: ativo, Tipo: bool
}
```

### Exemplo 3: Serialização genérica simples

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

fn toJson(comptime T: type, valor: T, writer: anytype) !void {
    const info = @typeInfo(T);
    switch (info) {
        .int, .comptime_int => try writer.print("{}", .{valor}),
        .float, .comptime_float => try writer.print("{d}", .{valor}),
        .bool => try writer.print("{}", .{valor}),
        .pointer => |ptr| {
            if (ptr.size == .slice and ptr.child == u8) {
                try writer.print("\"{s}\"", .{valor});
            }
        },
        .@"struct" => |s| {
            try writer.writeByte('{');
            inline for (s.fields, 0..) |campo, i| {
                if (i > 0) try writer.writeAll(", ");
                try writer.print("\"{s}\": ", .{campo.name});
                try toJson(campo.type, @field(valor, campo.name), writer);
            }
            try writer.writeByte('}');
        },
        else => try writer.writeAll("null"),
    }
}
```

## Casos de uso comuns

1. **Serialização/Deserialização genérica**: Iterar sobre campos de structs para converter automaticamente de/para JSON, MessagePack ou outros formatos.

2. **Validação de tipos genéricos**: Em funções genéricas, verificar se o tipo fornecido possui as propriedades necessárias (campos específicos, métodos, etc.).

3. **Geração automática de código**: Criar implementações de funções baseadas na estrutura de tipos, como `toString()`, comparação, hash, etc.

4. **Debug e logging**: Imprimir informações detalhadas sobre tipos para depuração em tempo de compilação.

5. **Frameworks e bibliotecas**: Construir abstrações que funcionam com qualquer tipo, como ORMs, frameworks web e sistemas de eventos.

## Trabalhando com enums via @typeInfo

Inspecionar enums é um dos usos mais comuns de `@typeInfo`. O campo `.@"enum"` fornece a lista de variantes, o tipo de tag e se o enum é exaustivo:

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

fn listarVariantes(comptime E: type) void {
    const info = @typeInfo(E);
    switch (info) {
        .@"enum" => |e| {
            std.debug.print("Enum com {} variantes (tag: {s}):\n", .{
                e.fields.len,
                @typeName(e.tag_type),
            });
            inline for (e.fields) |campo| {
                std.debug.print("  .{s} = {}\n", .{ campo.name, campo.value });
            }
        },
        else => @compileError("Esperava enum"),
    }
}

const Direcao = enum(u8) { norte = 0, sul = 1, leste = 2, oeste = 3 };

test "listar enum" {
    listarVariantes(Direcao);
}
```

## Verificação de interfaces em comptime

Um padrão poderoso é usar `@typeInfo` para verificar se um tipo implementa uma "interface" — um conjunto de métodos e campos esperados:

```zig
fn verificarInterface(comptime T: type) void {
    const info = @typeInfo(T);
    if (info != .@"struct") {
        @compileError(@typeName(T) ++ " deve ser uma struct");
    }

    // Verificar se tem método `format`
    if (!@hasDecl(T, "format")) {
        @compileError(@typeName(T) ++ " deve ter método `format`");
    }

    // Verificar campo obrigatório
    if (!@hasField(T, "id")) {
        @compileError(@typeName(T) ++ " deve ter campo `id`");
    }
}
```

Essa técnica é usada extensivamente na biblioteca padrão do Zig para garantir contratos de tipos em tempo de compilação, sem a necessidade de traits ou interfaces explícitas.

## Iteração sobre campos de struct em comptime

O padrão `inline for` com `@typeInfo` é essencial para metaprogramação genérica:

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

// Comparação automática de structs campo a campo
fn eql(comptime T: type, a: T, b: T) bool {
    const info = @typeInfo(T);
    if (info != .@"struct") @compileError("Apenas structs");

    inline for (info.@"struct".fields) |campo| {
        const va = @field(a, campo.name);
        const vb = @field(b, campo.name);
        if (va != vb) return false;
    }
    return true;
}

const Ponto = struct { x: f32, y: f32 };

test "comparação genérica" {
    const p1 = Ponto{ .x = 1.0, .y = 2.0 };
    const p2 = Ponto{ .x = 1.0, .y = 2.0 };
    const p3 = Ponto{ .x = 1.0, .y = 3.0 };

    try std.testing.expect(eql(Ponto, p1, p2));
    try std.testing.expect(!eql(Ponto, p1, p3));
}
```

## Perguntas Frequentes

**P: `@typeInfo` pode causar erros de compilação?**

R: Não por si só — mas o código que usa o resultado pode. Por exemplo, acessar `.@"struct"` em um tipo que não é struct causaria um erro em runtime de comptime (que é um erro de compilação). Use `switch` para tratar as variantes corretamente.

**P: Qual é a diferença entre `@typeInfo` e `@hasField`/`@hasDecl`?**

R: `@hasField` e `@hasDecl` são verificações pontuais (sim/não). `@typeInfo` fornece o conjunto completo de informações sobre o tipo, permitindo inspeção profunda, iteração sobre campos e verificações complexas. Para verificações simples, prefira `@hasField`/`@hasDecl` por clareza.

**P: Posso usar `@typeInfo` para inspecionar tipos de erro (`anyerror`, `!T`)?**

R: Sim. `@typeInfo(anyerror)` retorna `.error_set`, e `@typeInfo(!T)` retorna `.error_union` com os campos `.error_set` e `.payload`. Isso permite metaprogramação sobre conjuntos de erros.

## Builtins relacionados

- [@typeName](/builtins/type-name/) — Obtém o nome de um tipo como string
- [@TypeOf](/builtins/type-of/) — Obtém o tipo de uma expressão
- [@hasField](/builtins/has-field/) — Verifica se um tipo possui determinado campo
- [@hasDecl](/builtins/has-decl/) — Verifica se um tipo possui determinada declaração
- [@field](/builtins/field/) — Acessa campo de struct por nome

## Tutoriais relacionados

- [Metaprogramação com comptime](/tutoriais/comptime/)
- [Sistema de tipos do Zig](/tutoriais/tipos/)
- [Programação genérica em Zig](/tutoriais/generics/)
