@TypeOf em Zig — Referência e Exemplos

@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

@TypeOf(expressao) type

Também aceita múltiplas expressões:

@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

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

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

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.

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.

Builtins relacionados

  • @typeInfo — Obtém informações detalhadas sobre o tipo retornado
  • @typeName — Obtém o nome do tipo como string
  • @as — Conversão explícita para um tipo específico
  • @field — Acessa campo por nome dinâmico

Tutoriais relacionados

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.