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

# @TypeOf em Zig — Referência e Exemplos

Referência completa do @TypeOf em Zig. Aprenda a deduzir tipos de expressões em tempo de compilação com exemplos práticos.


# @TypeOf em Zig

O `@TypeOf` é um builtin que deduz e retorna o tipo de qualquer expressão em tempo de compilação. É o equivalente ao `decltype` do C++ ou ao `typeof` do JavaScript, mas resolvido estaticamente pelo compilador. Note que `@TypeOf` é escrito com T maiúsculo, diferente da maioria dos outros builtins — isso porque ele retorna um `type`, que em Zig é um valor de primeira classe em comptime.

## Sintaxe

```zig
@TypeOf(expressao) type
```

Também aceita múltiplas expressões:

```zig
@TypeOf(expr1, expr2, ..., exprN) type
```

## O que faz

O `@TypeOf` avalia o tipo de uma expressão sem executá-la. Quando recebe múltiplas expressões, retorna o tipo resultante da resolução de coerção entre todos os tipos — ou seja, o tipo para o qual todas as expressões podem ser implicitamente convertidas.

A expressão fornecida não é executada; apenas seu tipo é analisado. Isso significa que efeitos colaterais dentro da expressão não ocorrem.

## Parâmetros

- **expressao** (qualquer expressão válida): Uma ou mais expressões cujo tipo será deduzido. As expressões devem ser válidas sintaticamente e ter tipo determinável em tempo de compilação.

## Valor de retorno

Retorna um `type` — o tipo deduzido da expressão (ou o tipo comum quando múltiplas expressões são fornecidas).

## Exemplos práticos

### Exemplo 1: Dedução básica de tipos

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

test "dedução de tipo com @TypeOf" {
    const x: i32 = 42;
    const y = @as(f64, 3.14);
    const z = "Olá, Zig!";

    // @TypeOf deduz o tipo de cada expressão
    try std.testing.expect(@TypeOf(x) == i32);
    try std.testing.expect(@TypeOf(y) == f64);
    try std.testing.expect(@TypeOf(z) == *const [9:0]u8);

    // Funciona com expressões compostas
    try std.testing.expect(@TypeOf(x + 10) == i32);
    try std.testing.expect(@TypeOf(x > 0) == bool);
}
```

### Exemplo 2: Criando variáveis com tipo deduzido

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

fn calcular(a: anytype, b: anytype) @TypeOf(a + b) {
    return a + b;
}

fn criarArray(comptime tamanho: usize) [@TypeOf(tamanho)]u8 {
    // Aqui @TypeOf(tamanho) é usize, mas o uso prático é diferente
    // Geralmente @TypeOf é mais útil para retornos de funções genéricas
    return undefined;
}

test "retorno com tipo deduzido" {
    const resultado = calcular(@as(i32, 10), @as(i32, 20));
    try std.testing.expect(@TypeOf(resultado) == i32);
}
```

### Exemplo 3: Tipo comum entre múltiplas expressões

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

test "tipo comum com @TypeOf" {
    const a: i16 = 10;
    const b: i32 = 20;

    // Com múltiplos argumentos, retorna o tipo de coerção comum
    const TipoComum = @TypeOf(a, b);

    // i16 pode ser implicitamente convertido para i32, então o tipo comum é i32
    try std.testing.expect(TipoComum == i32);

    // Isso é útil para determinar o tipo de retorno em operações genéricas
    var resultado: TipoComum = a;
    resultado += b;
    try std.testing.expect(resultado == 30);
}
```

## Casos de uso comuns

1. **Retorno de funções genéricas**: Usar `@TypeOf` para definir o tipo de retorno de funções que operam sobre `anytype`, garantindo que o tipo de retorno seja consistente com os argumentos.

2. **Variáveis temporárias em código genérico**: Declarar variáveis intermediárias com o tipo correto deduzido automaticamente.

3. **Tipo comum para coerção**: Com múltiplos argumentos, encontrar o tipo para o qual todos os valores podem ser convertidos.

4. **Assertivas de tipo**: Verificar em tempo de compilação que uma expressão tem o tipo esperado.

5. **Metaprogramação**: Combinar com `@typeInfo` para inspecionar o tipo de expressões arbitrárias.

```zig
fn ehInteiro(valor: anytype) bool {
    return switch (@typeInfo(@TypeOf(valor))) {
        .int, .comptime_int => true,
        else => false,
    };
}
```

## Observações importantes

- O `@TypeOf` usa T maiúsculo por convenção do Zig: builtins que retornam `type` usam PascalCase.
- A expressão passada não é executada; não há efeitos colaterais.
- Quando múltiplos argumentos são passados e não existe um tipo comum de coerção, o compilador emite um erro.

## Uso com `anytype` em funções genéricas

O uso mais poderoso de `@TypeOf` é em funções que aceitam `anytype`. Como o compilador precisa gerar código específico para cada tipo, `@TypeOf` permite expressar o tipo de retorno em função dos argumentos:

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

// Retorna o maior dos dois valores, com tipo preservado
fn maximo(a: anytype, b: anytype) @TypeOf(a, b) {
    return if (a > b) a else b;
}

// Clamp genérico: limita valor entre min e max
fn clamp(valor: anytype, minimo: anytype, maximo_val: anytype) @TypeOf(valor, minimo, maximo_val) {
    if (valor < minimo) return minimo;
    if (valor > maximo_val) return maximo_val;
    return valor;
}

test "funções genéricas com @TypeOf" {
    try std.testing.expect(maximo(@as(i32, 10), @as(i32, 20)) == 20);
    try std.testing.expect(clamp(@as(f32, 1.5), @as(f32, 0.0), @as(f32, 1.0)) == 1.0);
}
```

## Combinação com `@typeInfo` para verificações em comptime

A combinação `@typeInfo(@TypeOf(valor))` é o padrão idiomático para inspecionar o tipo de um argumento `anytype` e tomar decisões em comptime:

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

fn imprimir(valor: anytype) void {
    const T = @TypeOf(valor);
    switch (@typeInfo(T)) {
        .int, .comptime_int => std.debug.print("inteiro: {}\n", .{valor}),
        .float, .comptime_float => std.debug.print("float: {d:.2}\n", .{valor}),
        .bool => std.debug.print("bool: {}\n", .{valor}),
        .pointer => |ptr| {
            if (ptr.size == .slice and ptr.child == u8) {
                std.debug.print("string: {s}\n", .{valor});
            } else {
                std.debug.print("ponteiro: *{s}\n", .{@typeName(ptr.child)});
            }
        },
        .@"struct" => std.debug.print("struct: {any}\n", .{valor}),
        else => std.debug.print("outro: {any}\n", .{valor}),
    }
}

test "imprimir genérico" {
    imprimir(@as(i32, 42));
    imprimir(@as(f64, 3.14));
    imprimir(true);
    imprimir("Olá, Zig!");
}
```

## Diferença entre `@TypeOf` e inferência de tipo com `var`/`const`

Em Zig, `const x = expr` já infere o tipo de `x` automaticamente. `@TypeOf` é necessário quando você precisa usar o tipo em outros contextos — como parâmetros de função, tipos de retorno, ou para raciocinar explicitamente sobre ele:

```zig
// Inferência de tipo automática (mais comum)
const x = @as(i32, 42); // x tem tipo i32, inferido automaticamente

// @TypeOf é necessário quando você precisa do tipo como valor
const T = @TypeOf(x);        // T == i32, um type como valor comptime
const info = @typeInfo(T);   // inspecionar o tipo
const nome = @typeName(T);   // obter o nome como string
```

## Comportamento com expressões de efeito colateral

Uma propriedade importante: `@TypeOf` **não executa** a expressão. Isso significa que efeitos colaterais (chamadas de função, modificações de variáveis) dentro da expressão passada para `@TypeOf` não ocorrem:

```zig
var contador: u32 = 0;

fn incrementar() u32 {
    contador += 1; // este efeito colateral NÃO ocorre dentro de @TypeOf
    return contador;
}

// A expressão é analisada sintaticamente para determinar o tipo,
// mas a função não é chamada
const T = @TypeOf(incrementar()); // T == u32, mas incrementar() não executa
```

## Comparação com equivalente em C/C++

Em C, não há equivalente direto. Em C++, existe `decltype`:

```cpp
// C++: decltype
int x = 42;
decltype(x) y = 10;  // y tem tipo int
decltype(x + 3.14) z; // z tem tipo double (coerção implícita)
```

Em Zig, `@TypeOf` é semanticamente similar ao `decltype` do C++, mas com a vantagem de trabalhar com o sistema de tipos mais rigoroso do Zig e sem coerções implícitas inesperadas:

```zig
// Zig: @TypeOf
const x: i32 = 42;
const T = @TypeOf(x);    // T == i32
var y: T = 10;           // y tem tipo i32, explícito
```

## Perguntas Frequentes

**P: Por que `@TypeOf` usa T maiúsculo enquanto outros builtins usam minúscula?**

R: Por convenção do Zig, builtins que retornam `type` usam PascalCase. Como `type` é um valor de primeira classe em Zig (pode ser armazenado em variáveis, passado como argumento), a convenção PascalCase sinaliza que o resultado é um tipo. Outros exemplos: `@This()`, `@Frame()`.

**P: O que acontece se as expressões passadas para `@TypeOf` não têm tipo comum?**

R: O compilador emite um erro. Por exemplo, `@TypeOf(@as(i32, 1), "texto")` falha porque `i32` e `*const [5:0]u8` não têm tipo comum por coerção implícita.

**P: `@TypeOf` pode ser usado para deduzir o tipo de retorno de uma função recursiva?**

R: Em geral, não para funções com recursão não resolvida, pois criaria circularidade na inferência. Para funções recursivas, declare o tipo de retorno explicitamente.

## Builtins relacionados

- [@typeInfo](/builtins/type-info/) — Obtém informações detalhadas sobre o tipo retornado
- [@typeName](/builtins/type-name/) — Obtém o nome do tipo como string
- [@as](/builtins/as/) — Conversão explícita para um tipo específico
- [@field](/builtins/field/) — Acessa campo por nome dinâmico

## Tutoriais relacionados

- [Sistema de tipos do Zig](/tutoriais/tipos/)
- [Funções genéricas com anytype](/tutoriais/generics/)
- [Metaprogramação com comptime](/tutoriais/comptime/)
