---
title: "@hasField em Zig — Referência e Exemplos"
url: "https://ziglang.com.br/builtins/@hasfield-em-zig-refer%C3%AAncia-e-exemplos/"
markdown_url: "https://ziglang.com.br/builtins/@hasfield-em-zig-refer%C3%AAncia-e-exemplos.MD"
description: "Referência completa do @hasField em Zig. Aprenda a verificar se um tipo possui determinado campo em comptime com exemplos."
date: "2026-02-21"
author: "Zig Brasil"
---

# @hasField em Zig — Referência e Exemplos

Referência completa do @hasField em Zig. Aprenda a verificar se um tipo possui determinado campo em comptime com exemplos.


# @hasField em Zig

O `@hasField` verifica se um tipo (struct, union ou enum) possui um campo com o nome especificado. Retorna `true` ou `false` em tempo de compilação. É essencial para escrever código genérico robusto que precisa se adaptar a diferentes tipos sem causar erros de compilação.

## Sintaxe

```zig
@hasField(comptime T: type, comptime nome: []const u8) bool
```

## O que faz

O `@hasField` consulta a definição do tipo fornecido para verificar se ele contém um campo com o nome especificado. A verificação é realizada em tempo de compilação, sem nenhum custo em tempo de execução. Retorna `true` se o campo existir, `false` caso contrário.

## Parâmetros

- **T** (`type`, comptime): O tipo a ser inspecionado. Deve ser uma struct, union ou enum.
- **nome** (`[]const u8`, comptime): O nome do campo a ser verificado, como string.

## Valor de retorno

Retorna `bool` (comptime) — `true` se o campo existir no tipo, `false` caso contrário.

## Exemplos práticos

### Exemplo 1: Verificação básica de campos

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

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

test "verificar existência de campos" {
    try std.testing.expect(@hasField(Pessoa, "nome") == true);
    try std.testing.expect(@hasField(Pessoa, "idade") == true);
    try std.testing.expect(@hasField(Pessoa, "email") == true);
    try std.testing.expect(@hasField(Pessoa, "telefone") == false);
    try std.testing.expect(@hasField(Pessoa, "cpf") == false);
}
```

### Exemplo 2: Mapeamento adaptativo entre tipos

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

fn copiarCamposComuns(comptime Destino: type, comptime Origem: type, origem: Origem) Destino {
    var resultado: Destino = undefined;
    const campos_destino = @typeInfo(Destino).@"struct".fields;

    inline for (campos_destino) |campo| {
        if (@hasField(Origem, campo.name)) {
            @field(resultado, campo.name) = @field(origem, campo.name);
        } else {
            // Usar valor padrão se disponível, ou zero
            if (campo.default_value) |default_ptr| {
                const ptr: *const campo.type = @ptrCast(@alignCast(default_ptr));
                @field(resultado, campo.name) = ptr.*;
            } else {
                @field(resultado, campo.name) = std.mem.zeroes(campo.type);
            }
        }
    }

    return resultado;
}

const UsuarioDb = struct {
    id: u64,
    nome: []const u8,
    email: []const u8,
    hash_senha: []const u8,
};

const UsuarioDto = struct {
    id: u64,
    nome: []const u8,
    email: []const u8,
    // Sem hash_senha — dados sensíveis não são expostos
};

test "copiar campos comuns" {
    const db = UsuarioDb{
        .id = 1,
        .nome = "João",
        .email = "joao@ex.com",
        .hash_senha = "abc123",
    };

    const dto = copiarCamposComuns(UsuarioDto, UsuarioDb, db);
    try std.testing.expect(dto.id == 1);
    try std.testing.expectEqualStrings("João", dto.nome);
    try std.testing.expectEqualStrings("joao@ex.com", dto.email);
}
```

### Exemplo 3: Interface baseada em duck typing

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

fn tamanho(valor: anytype) usize {
    const T = @TypeOf(valor);

    // Verificar diferentes formas de obter o "tamanho"
    if (@hasField(T, "len")) {
        return @field(valor, "len");
    } else if (@hasField(T, "count")) {
        return @field(valor, "count");
    } else if (@hasField(T, "tamanho")) {
        return @field(valor, "tamanho");
    } else {
        @compileError("Tipo " ++ @typeName(T) ++ " não possui campo de tamanho");
    }
}

test "duck typing para tamanho" {
    const ComLen = struct { len: usize, dados: u32 };
    const ComCount = struct { count: usize, tipo: u8 };

    const a = ComLen{ .len = 10, .dados = 0 };
    const b = ComCount{ .count = 5, .tipo = 1 };

    try std.testing.expect(tamanho(a) == 10);
    try std.testing.expect(tamanho(b) == 5);
}
```

## Casos de uso comuns

1. **Mapeamento entre tipos**: Copiar campos comuns entre structs de tipos diferentes (ex: DTO para modelo de banco).
2. **Duck typing em comptime**: Verificar se um tipo implementa uma "interface" baseada na presença de campos.
3. **Código genérico adaptativo**: Escrever funções que se adaptam a diferentes tipos sem exigir que todos tenham os mesmos campos.
4. **Deserialização tolerante**: Ignorar campos do JSON/dados que não existem na struct de destino.
5. **Validação de schemas**: Verificar que tipos de configuração possuem os campos obrigatórios.

## Validação de contratos em comptime

Um padrão poderoso é usar `@hasField` junto com `@compileError` para impor contratos em tipos genéricos, gerando mensagens de erro claras quando um tipo não satisfaz os requisitos:

```zig
fn assertTemCamposObrigatorios(comptime T: type) void {
    const campos_obrigatorios = [_][]const u8{ "id", "nome", "criado_em" };
    inline for (campos_obrigatorios) |campo| {
        if (!@hasField(T, campo)) {
            @compileError("Tipo " ++ @typeName(T) ++ " deve ter o campo '" ++ campo ++ "'");
        }
    }
}

fn salvarNoDb(comptime T: type, valor: T) void {
    comptime assertTemCamposObrigatorios(T);
    // Pode usar valor.id, valor.nome, valor.criado_em com segurança
    _ = valor;
}
```

Essa técnica é especialmente útil em frameworks e bibliotecas onde você precisa garantir que tipos definidos pelo usuário sigam um contrato.

## Iteração segura com `@hasField` e `@field`

O `@hasField` é frequentemente usado junto com `@field` para acessar campos de forma segura em funções genéricas:

```zig
fn obterTimestamp(valor: anytype) ?i64 {
    const T = @TypeOf(valor);
    if (@hasField(T, "timestamp")) {
        return @field(valor, "timestamp");
    } else if (@hasField(T, "criado_em")) {
        return @field(valor, "criado_em");
    } else if (@hasField(T, "data")) {
        return @field(valor, "data");
    }
    return null;
}
```

Esse padrão de "tentar vários nomes de campo" é uma forma de duck typing seguro em Zig.

## Comparação com reflexão em outras linguagens

Em Python ou JavaScript, a verificação de campos é feita em runtime com `hasattr()` ou `in`:

```python
if hasattr(obj, 'nome'):  # runtime, com overhead
    print(obj.nome)
```

Em Zig, `@hasField` opera exclusivamente em tempo de compilação — sem overhead em runtime, com verificação de tipos completa e dead code elimination automática pelo compilador.

## Perguntas Frequentes

**P: `@hasField` funciona com unions e enums além de structs?**

Sim. `@hasField` funciona com structs, unions (tagged e bare) e enums. Para unions, verifica os campos (variantes). Para enums, verifica as variantes.

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

`@hasField` verifica campos de dados (membros que existem em cada instância da struct). `@hasDecl` verifica declarações do namespace do tipo — funções, constantes e tipos aninhados. São complementares: use `@hasField` para campos e `@hasDecl` para métodos e constantes.

**P: É possível obter o tipo de um campo verificado com `@hasField`?**

Sim. Após verificar a existência com `@hasField`, use `@typeInfo(T).@"struct".fields` para encontrar o campo e acessar seu tipo, ou use `@TypeOf(@field(instancia, "nome"))` diretamente.

## Builtins relacionados

- [@field](/builtins/field/) — Acessa o campo após verificar sua existência
- [@hasDecl](/builtins/has-decl/) — Verifica existência de declarações (funções, constantes)
- [@typeInfo](/builtins/type-info/) — Informações completas sobre o tipo
- [@compileError](/builtins/compile-error/) — Gera erro quando campo obrigatório está ausente

## Tutoriais relacionados

- [Metaprogramação com comptime](/tutoriais/comptime/)
- [Programação genérica em Zig](/tutoriais/generics/)
- [Padrões de design em Zig](/tutoriais/design-patterns/)
