---
title: "Modulo std::any em Rust: Any e TypeId"
url: "https://rustlang.com.br/stdlib/any-module/"
markdown_url: "https://rustlang.com.br/stdlib/any-module.MD"
description: "Guia completo do modulo std::any em Rust: Any trait, TypeId, verificacao de tipos em runtime, downcast, type erasure e padroes de plugins."
date: "2026-02-23"
author: "Equipe Rust Brasil"
---

# Modulo std::any em Rust: Any e TypeId

Guia completo do modulo std::any em Rust: Any trait, TypeId, verificacao de tipos em runtime, downcast, type erasure e padroes de plugins.


## Visao Geral do Modulo std::any

O modulo `std::any` fornece mecanismos para **verificacao de tipos em tempo de execucao** (runtime). Em um sistema de tipos estatico como o de Rust, normalmente todos os tipos sao conhecidos em tempo de compilacao. Porem, ha cenarios em que voce precisa trabalhar com tipos desconhecidos — como sistemas de plugins, registros de eventos heterogeneos ou frameworks de injecao de dependencia.

Os dois tipos principais sao:
- **`Any`** — trait que permite a qualquer tipo `'static` ser inspecionado e convertido (downcast) em runtime
- **`TypeId`** — identificador unico de um tipo, util para comparacoes

O `std::any` e a resposta do Rust para cenarios que em outras linguagens seriam resolvidos com reflexao (reflection). Ele oferece uma forma controlada e segura de fazer type erasure e recuperacao.

---

## Tipos e Funcoes Principais

### Trait Any

A trait `Any` e implementada automaticamente para todo tipo que satisfaca `'static` (ou seja, nao contem referencias com lifetimes nao-estaticos).

| Metodo | Descricao |
|---|---|
| `.type_id()` | Retorna o `TypeId` do valor |
| `.is::<T>()` | Verifica se o valor e do tipo `T` |
| `.downcast_ref::<T>()` | Tenta converter para `&T` (retorna `Option`) |
| `.downcast_mut::<T>()` | Tenta converter para `&mut T` (retorna `Option`) |

### Box<dyn Any>

| Metodo | Descricao |
|---|---|
| `.downcast::<T>()` | Tenta converter para `Box<T>` (retorna `Result`) |
| `.is::<T>()` | Verifica se o conteudo e do tipo `T` |

### TypeId

| Metodo | Descricao |
|---|---|
| `TypeId::of::<T>()` | Retorna o `TypeId` de um tipo |

A comparacao entre `TypeId`s e constante e extremamente rapida.

---

## Exemplos Praticos

### 1. Verificacao de Tipos em Runtime

```rust
use std::any::Any;

fn inspecionar(valor: &dyn Any) {
    if valor.is::<i32>() {
        let numero = valor.downcast_ref::<i32>().unwrap();
        println!("E um i32: {numero}");
    } else if valor.is::<String>() {
        let texto = valor.downcast_ref::<String>().unwrap();
        println!("E uma String: \"{texto}\"");
    } else if valor.is::<f64>() {
        let decimal = valor.downcast_ref::<f64>().unwrap();
        println!("E um f64: {decimal}");
    } else {
        println!("Tipo desconhecido (TypeId: {:?})", valor.type_id());
    }
}

fn main() {
    inspecionar(&42i32);
    inspecionar(&String::from("Rust"));
    inspecionar(&3.14f64);
    inspecionar(&true); // Tipo desconhecido
}
```

### 2. Colecao Heterogenea com Box<dyn Any>

```rust
use std::any::Any;

struct Registro {
    campos: Vec<(&'static str, Box<dyn Any>)>,
}

impl Registro {
    fn new() -> Self {
        Registro { campos: Vec::new() }
    }

    fn inserir<T: Any>(&mut self, nome: &'static str, valor: T) {
        self.campos.push((nome, Box::new(valor)));
    }

    fn obter<T: Any>(&self, nome: &str) -> Option<&T> {
        self.campos
            .iter()
            .find(|(n, _)| *n == nome)
            .and_then(|(_, v)| v.downcast_ref::<T>())
    }

    fn remover<T: Any>(&mut self, nome: &str) -> Option<T> {
        let pos = self.campos.iter().position(|(n, _)| *n == nome)?;
        let (_, caixa) = self.campos.remove(pos);
        caixa.downcast::<T>().ok().map(|b| *b)
    }
}

fn main() {
    let mut reg = Registro::new();
    reg.inserir("nome", String::from("Alice"));
    reg.inserir("idade", 30u32);
    reg.inserir("ativo", true);
    reg.inserir("salario", 5500.0f64);

    // Recuperando com tipo correto
    if let Some(nome) = reg.obter::<String>("nome") {
        println!("Nome: {nome}");
    }

    if let Some(idade) = reg.obter::<u32>("idade") {
        println!("Idade: {idade}");
    }

    // Tipo incorreto retorna None
    let errado = reg.obter::<i32>("idade"); // None (e u32, nao i32!)
    println!("Tipo errado: {errado:?}");

    // Removendo com ownership
    if let Some(salario) = reg.remover::<f64>("salario") {
        println!("Salario removido: {salario}");
    }
}
```

### 3. Sistema de Plugins com Any

```rust
use std::any::{Any, TypeId};
use std::collections::HashMap;

trait Plugin: Any {
    fn nome(&self) -> &str;
    fn executar(&self);
    fn as_any(&self) -> &dyn Any;
}

struct PluginLog {
    prefixo: String,
}

impl Plugin for PluginLog {
    fn nome(&self) -> &str { "Logger" }

    fn executar(&self) {
        println!("[{}] Plugin de log executado", self.prefixo);
    }

    fn as_any(&self) -> &dyn Any { self }
}

struct PluginMetrica {
    contador: u64,
}

impl Plugin for PluginMetrica {
    fn nome(&self) -> &str { "Metricas" }

    fn executar(&self) {
        println!("Metricas coletadas: {} eventos", self.contador);
    }

    fn as_any(&self) -> &dyn Any { self }
}

struct GerenciadorPlugins {
    plugins: HashMap<TypeId, Box<dyn Plugin>>,
}

impl GerenciadorPlugins {
    fn new() -> Self {
        GerenciadorPlugins {
            plugins: HashMap::new(),
        }
    }

    fn registrar<P: Plugin + 'static>(&mut self, plugin: P) {
        let tipo = TypeId::of::<P>();
        println!("Registrando plugin: {}", plugin.nome());
        self.plugins.insert(tipo, Box::new(plugin));
    }

    fn obter<P: Plugin + 'static>(&self) -> Option<&P> {
        let tipo = TypeId::of::<P>();
        self.plugins
            .get(&tipo)
            .and_then(|p| p.as_any().downcast_ref::<P>())
    }

    fn executar_todos(&self) {
        for plugin in self.plugins.values() {
            plugin.executar();
        }
    }
}

fn main() {
    let mut gerenciador = GerenciadorPlugins::new();

    gerenciador.registrar(PluginLog {
        prefixo: "APP".into(),
    });
    gerenciador.registrar(PluginMetrica {
        contador: 1500,
    });

    // Executar todos os plugins
    gerenciador.executar_todos();

    // Acessar um plugin especifico pelo tipo
    if let Some(log) = gerenciador.obter::<PluginLog>() {
        println!("Prefixo do logger: {}", log.prefixo);
    }
}
```

### 4. TypeId para Comparacao Eficiente

```rust
use std::any::TypeId;

fn tipo_para_nome(id: TypeId) -> &'static str {
    if id == TypeId::of::<i32>() {
        "i32"
    } else if id == TypeId::of::<String>() {
        "String"
    } else if id == TypeId::of::<Vec<u8>>() {
        "Vec<u8>"
    } else {
        "desconhecido"
    }
}

fn nome_do_tipo<T: 'static>() -> &'static str {
    tipo_para_nome(TypeId::of::<T>())
}

fn main() {
    println!("{}", nome_do_tipo::<i32>());      // i32
    println!("{}", nome_do_tipo::<String>());    // String
    println!("{}", nome_do_tipo::<Vec<u8>>());   // Vec<u8>
    println!("{}", nome_do_tipo::<bool>());      // desconhecido

    // TypeId e Copy, barato de comparar e pode ser usado como chave
    let id1 = TypeId::of::<String>();
    let id2 = TypeId::of::<String>();
    let id3 = TypeId::of::<&str>();

    assert_eq!(id1, id2);
    assert_ne!(id1, id3); // String e &str sao tipos diferentes!
}
```

### 5. Type Erasure e Recuperacao

```rust
use std::any::Any;

struct Cache {
    dados: Vec<Box<dyn Any>>,
}

impl Cache {
    fn new() -> Self {
        Cache { dados: Vec::new() }
    }

    fn armazenar<T: Any>(&mut self, valor: T) -> usize {
        let indice = self.dados.len();
        self.dados.push(Box::new(valor));
        indice
    }

    fn recuperar<T: Any>(&self, indice: usize) -> Option<&T> {
        self.dados.get(indice)?.downcast_ref::<T>()
    }

    fn recuperar_owned<T: Any>(mut self, indice: usize) -> Option<T> {
        if indice >= self.dados.len() {
            return None;
        }
        let item = self.dados.swap_remove(indice);
        item.downcast::<T>().ok().map(|b| *b)
    }
}

fn main() {
    let mut cache = Cache::new();

    let i_str = cache.armazenar(String::from("cache de dados"));
    let i_num = cache.armazenar(42u64);
    let i_vec = cache.armazenar(vec![1, 2, 3]);

    // Recuperar como referencia tipada
    if let Some(texto) = cache.recuperar::<String>(i_str) {
        println!("String: {texto}");
    }

    if let Some(num) = cache.recuperar::<u64>(i_num) {
        println!("Numero: {num}");
    }

    if let Some(lista) = cache.recuperar::<Vec<i32>>(i_vec) {
        println!("Vec: {lista:?}");
    }

    // Tipo errado retorna None — sem panic
    assert!(cache.recuperar::<bool>(i_str).is_none());
}
```

---

## Padroes Comuns

### Padrao as_any() em Traits

Quando voce tem uma trait customizada e precisa fazer downcast, inclua um metodo `as_any()`:

```rust
use std::any::Any;

trait Componente: Any {
    fn atualizar(&mut self);
    fn as_any(&self) -> &dyn Any;
    fn as_any_mut(&mut self) -> &mut dyn Any;
}
```

Este padrao e necessario porque `dyn MinhaTraitCustomizada` nao pode ser convertido diretamente para `dyn Any`.

### Restricao 'static

`Any` requer que o tipo seja `'static`, ou seja, nao contenha referencias com lifetimes nao-estaticos. Isso significa que voce nao pode usar `Any` com tipos como `&'a str` (onde `'a` nao e `'static`). Use `String` ou tipos owned.

### TypeId como Chave de HashMap

`TypeId` implementa `Hash` e `Eq`, sendo perfeito como chave para mapas tipo-valor:

```rust
use std::any::TypeId;
use std::collections::HashMap;

type TypeMap = HashMap<TypeId, Box<dyn std::any::Any>>;
```

---

## Quando Usar (e Quando Nao Usar)

**Use `std::any` quando:**
- Precisar de colecoes heterogeneas (valores de tipos diferentes)
- Implementando sistemas de plugins ou extensoes
- Criando registros de servicos ou injecao de dependencia
- Precisar comparar tipos em runtime

**Nao use `std::any` quando:**
- Enums resolverem o problema (preferivel a type erasure)
- Generics forem suficientes (resolucao em compile-time e melhor)
- Trait objects normais (`dyn Trait`) atenderem a necessidade
- Estiver tentando emular heranca de classes OOP

**Dica de performance:** `TypeId::of::<T>()` e uma operacao const — e resolvida em tempo de compilacao. `downcast_ref` envolve apenas uma comparacao de `TypeId`, sendo extremamente rapida (tempo constante).

**Limitacao importante:** `Any` so funciona com tipos `'static`. Se voce precisa de type erasure com lifetimes arbitrarios, considere usar trait objects com generics ou crates como `typemap`.

---

## Veja Tambem

- [Trait Objects vs Generics](/artigos/trait-objects-vs-generics/) — quando usar cada abordagem
- [Modulo std::marker](/stdlib/marker-module/) — traits de marcacao como `Sized` e `Send`
- [Modulo std::convert](/stdlib/convert-module/) — conversoes seguras entre tipos
- [O Prelude do Rust](/stdlib/prelude/) — traits importadas automaticamente
- [Documentacao oficial — std::any](https://doc.rust-lang.org/std/any/index.html)
