@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
Retorno de funções genéricas: Usar
@TypeOfpara definir o tipo de retorno de funções que operam sobreanytype, garantindo que o tipo de retorno seja consistente com os argumentos.Variáveis temporárias em código genérico: Declarar variáveis intermediárias com o tipo correto deduzido automaticamente.
Tipo comum para coerção: Com múltiplos argumentos, encontrar o tipo para o qual todos os valores podem ser convertidos.
Assertivas de tipo: Verificar em tempo de compilação que uma expressão tem o tipo esperado.
Metaprogramação: Combinar com
@typeInfopara 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
@TypeOfusa T maiúsculo por convenção do Zig: builtins que retornamtypeusam 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