assert_type e reveal_type: teste inferência de tipos

Publicado em: 29/08/2026
Tempo de leitura: 6 minutos
Close-up of a laptop screen with code and a coffee mug, perfect for tech abstract themes.

typing.assert_type e typing.reveal_type ajudam a testar e compreender a inferência de tipos. reveal_type() pede ao analisador que mostre o tipo inferido de uma expressão. assert_type() declara qual tipo o programador espera e permite transformar essa expectativa em um teste estático que falha quando a inferência muda.

Essas ferramentas são especialmente úteis ao desenvolver bibliotecas, overloads, genéricos, Protocols, TypedDicts, decoradores e funções que refinam tipos. Neste guia, você aprenderá a usá-las em arquivos de teste, CI, debugging de anotações e manutenção de APIs.

O que reveal_type faz

from typing import reveal_type

valor = [1, 2, 3]
reveal_type(valor)

Um analisador pode informar que valor é list[int]. A mensagem aparece durante a análise estática. Em runtime, o comportamento depende da implementação da função e pode produzir uma saída diagnóstica, mas o uso principal é com mypy, pyright ou ferramentas equivalentes.

Revelando expressões intermediárias

dados: dict[str, int | None] = {"a": 1}
valor = dados.get("a")
reveal_type(valor)

O resultado esperado é uma união como int | None. Esse diagnóstico ajuda a entender por que o analisador exige uma verificação antes de operações numéricas.

Refinamento por condição

if valor is not None:
    reveal_type(valor)
    print(valor + 1)

Dentro do ramo, o tipo deve ser refinado para int. reveal_type permite confirmar se o fluxo foi interpretado como esperado.

O que assert_type faz

from typing import assert_type

resultado = len("python")
assert_type(resultado, int)

O analisador compara o tipo inferido de resultado com o tipo esperado. Se não corresponder segundo suas regras, gera um erro. A função retorna o primeiro argumento em runtime e não converte nem valida o valor.

assert_type não é isinstance

valor: object = 10
assert_type(valor, int)  # deve falhar estaticamente

Embora o valor concreto seja um inteiro naquela execução, a variável foi declarada como object. assert_type testa a informação estática disponível, não o tipo observado em runtime.

Testando uma função genérica

from typing import TypeVar

T = TypeVar("T")

def primeiro(itens: list[T]) -> T:
    return itens[0]

assert_type(primeiro([1, 2]), int)
assert_type(primeiro(["a", "b"]), str)

Esses testes confirmam que o parâmetro genérico é propagado ao retorno.

Testando overloads

from typing import Literal, overload

@overload
def ler(*, binario: Literal[False] = False) -> str: ...
@overload
def ler(*, binario: Literal[True]) -> bytes: ...

def ler(*, binario: bool = False) -> str | bytes:
    return b"dados" if binario else "dados"

assert_type(ler(), str)
assert_type(ler(binario=True), bytes)

Uma alteração na ordem ou assinatura dos overloads pode quebrar a inferência. assert_type captura a regressão sem precisar executar a função.

Testando Literal

modo = "rapido"
reveal_type(modo)

modo_literal: Literal["rapido"] = "rapido"
assert_type(modo_literal, Literal["rapido"])

Variáveis mutáveis podem ser ampliadas para str, enquanto anotações explícitas preservam o valor literal. reveal_type mostra essa diferença.

Testando TypedDict

from typing import TypedDict

class Usuario(TypedDict):
    id: int
    nome: str

usuario: Usuario = {"id": 1, "nome": "Ana"}
assert_type(usuario["id"], int)
assert_type(usuario["nome"], str)

Chaves opcionais exigem teste de presença. É útil revelar o tipo antes e depois de if "chave" in dados.

Testando TypeGuard e TypeIs

from typing import TypeGuard

def eh_str(valor: object) -> TypeGuard[str]:
    return isinstance(valor, str)

item: object = "x"
if eh_str(item):
    assert_type(item, str)

O teste confirma que o predicado refina o ramo verdadeiro. Para TypeIs, também teste o ramo falso. Consulte TypeGuard no Python.

Testando Protocol

from typing import Protocol

class Fechavel(Protocol):
    def fechar(self) -> None: ...

class Arquivo:
    def fechar(self) -> None: ...

arquivo = Arquivo()
assert_type(arquivo, Arquivo)

fechavel: Fechavel = arquivo
assert_type(fechavel, Fechavel)

assert_type verifica o tipo estático da variável, não apenas a compatibilidade estrutural da expressão.

Decoradores e perda de assinatura

Decoradores mal tipados frequentemente transformam funções precisas em Callable[..., Any]. Use reveal_type na função decorada e em seu retorno:

@meu_decorador
def buscar(id_: int) -> str:
    ...

reveal_type(buscar)
assert_type(buscar(1), str)

ParamSpec e TypeVar podem preservar a assinatura. O guia sobre ParamSpec no Python mostra esse padrão.

Arquivos de testes estáticos

Crie arquivos como tests/typing/test_api.py que não precisam ser executados no pytest. O CI roda o analisador sobre eles. Esses testes documentam a experiência esperada do usuário da biblioteca.

Testes positivos e negativos

assert_type cobre expectativas positivas. Para chamadas que devem falhar, use mecanismos do analisador, comentários de erro esperado ou ferramentas como pytest para type checker. A sintaxe varia entre ecossistemas.

Não dependa da mensagem textual

Mensagens de reveal_type podem variar entre analisadores. Use assert_type quando precisar de uma expectativa automatizada. reveal_type é melhor para exploração e debugging.

Tipos equivalentes e normalização

list[int] e formas antigas podem ser tratadas como equivalentes. Uniões podem aparecer em ordem diferente. O analisador decide equivalência sem depender da representação de string.

Any pode esconder problemas

valor: object = obter_dado()
reveal_type(valor)

Se uma dependência retorna Any, muitas operações passam sem verificação. Adicione assert_type em fronteiras para detectar quando Any invade a API. Algumas configurações do analisador podem tornar o teste com Any mais rigoroso.

Never e código inalcançável

Em ramos exaustivos, reveal_type pode mostrar Never. Isso ajuda a confirmar que uma união foi totalmente tratada. O guia sobre Never no Python aborda assert_never().

Self e métodos fluentes

builder = BuilderEspecial().configurar()
assert_type(builder, BuilderEspecial)

Esse teste garante que um método com Self preserva subclasses. É valioso para factories e APIs fluentes.

Tipos variádicos

TypeVarTuple e Unpack podem produzir inferências difíceis de observar. assert_type documenta a forma resultante:

tupla = adicionar_prefixo((1, "a"))
assert_type(tupla, tuple[str, int, str])

Comportamento em runtime

assert_type(valor, Tipo) retorna valor sem fazer checagem. reveal_type(valor) também não substitui validação. Não use essas funções para proteger entradas de usuário ou garantir tipos durante execução.

Remover reveal_type antes da produção

Chamadas de reveal_type são úteis durante desenvolvimento, mas podem gerar saída em runtime ou poluir o código. Mantenha-as em testes de tipagem ou remova após o diagnóstico.

Compatibilidade de versões

Use typing_extensions.assert_type e recursos relacionados quando necessário. O comportamento estático depende mais da versão do analisador que do interpretador. Fixe versões no CI para evitar mudanças inesperadas.

Comparando analisadores

Mypy e pyright podem inferir detalhes diferentes em casos complexos. Se a biblioteca promete suporte aos dois, execute os mesmos testes com ambos. Evite depender de um comportamento não especificado apenas porque um analisador o aceita.

Erros comuns

  • Esperar validação em runtime: assert_type não chama isinstance.
  • Deixar reveal_type no caminho de produção: pode gerar saída desnecessária.
  • Testar apenas implementação: teste também a API vista pelo consumidor.
  • Aceitar Any sem perceber: ele pode fazer assertivas perderem valor.
  • Comparar strings de diagnóstico: mensagens variam.
  • Não fixar o analisador: mudanças de versão podem alterar inferência.

Exemplo completo: API de cache

from typing import TypeVar, overload, assert_type

T = TypeVar("T")
_AUSENTE = object()

@overload
def obter(chave: str) -> object: ...
@overload
def obter(chave: str, default: T) -> object | T: ...

def obter(chave: str, default: object = _AUSENTE) -> object:
    ...

assert_type(obter("x"), object)
assert_type(obter("x", 0), object | int)
assert_type(obter("x", None), object | None)

Os testes registram a relação entre default e retorno. Se a implementação ou os overloads mudarem, o CI informa a regressão.

Estratégia para bibliotecas

Crie uma pasta de casos de uso reais. Importe a biblioteca como um consumidor externo. Teste inferência de retornos, erros esperados, subclasses, overloads e genéricos. Não teste apenas funções internas, pois o empacotamento e os arquivos .pyi também podem alterar os tipos públicos.

Conclusão

reveal_type() é uma lente para investigar o que o analisador inferiu. assert_type() transforma a expectativa em um contrato testável. Juntos, eles ajudam a desenvolver APIs tipadas previsíveis e a detectar regressões antes da publicação.

A documentação oficial de assert_type e reveal_type no módulo typing detalha o comportamento. Use reveal_type para explorar, assert_type para automatizar e sempre execute os testes com as mesmas configurações de tipagem usadas pelo projeto.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Close-up image of a woman's hand holding a stack of spiral-bound notebooks and papers against a dark background.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    get_type_hints no Python: leia anotações

    Aprenda get_type_hints no Python para resolver referências futuras, ler Annotated e inspecionar funções e classes com segurança.

    Ler mais

    Tempo de leitura: 6 minutos
    29/08/2026
    A laptop screen showing a code editor with visible programming code in a dimly lit environment.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    runtime_checkable no Python: Protocol em runtime

    Aprenda runtime_checkable no Python para testar Protocol com isinstance, entender limites e criar contratos estruturais seguros.

    Ler mais

    Tempo de leitura: 6 minutos
    29/08/2026
    Close-up of a laptop screen with code and a coffee mug, perfect for tech abstract themes.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    Unpack no Python: kwargs e tipos variádicos

    Aprenda typing.Unpack no Python para tipar **kwargs com TypedDict, expandir tuplas variádicas e preservar assinaturas precisas.

    Ler mais

    Tempo de leitura: 6 minutos
    29/08/2026
    High-angle view of woman coding on a laptop, with a Python book nearby. Ideal for programming and tech content.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    Required e NotRequired: campos opcionais no TypedDict

    Aprenda Required e NotRequired no Python para controlar chaves obrigatórias e opcionais em TypedDict com contratos claros.

    Ler mais

    Tempo de leitura: 6 minutos
    29/08/2026
    Detailed view of programming code in a dark theme on a computer screen.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    ReadOnly no Python: proteja campos TypedDict

    Aprenda ReadOnly no Python para marcar campos TypedDict como somente leitura, modelar contratos imutáveis e evitar alterações acidentais.

    Ler mais

    Tempo de leitura: 6 minutos
    29/08/2026
    A detailed image of a reticulated python showcasing its patterned scales and intricate skin texture.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    TypeAliasType no Python: aliases em runtime

    Aprenda TypeAliasType no Python para criar aliases explícitos, inspecionar tipos em runtime e modelar APIs genéricas com segurança.

    Ler mais

    Tempo de leitura: 7 minutos
    29/08/2026