DEV Community

Cover image for Type Hints no Python, FastAPI e o Espectro entre Tipagem Estática e Dinâmica
Felipe Cezar
Felipe Cezar

Posted on

Type Hints no Python, FastAPI e o Espectro entre Tipagem Estática e Dinâmica

Você sabia que Python, uma linguagem dinamicamente tipada, permite que você escreva código que parece estaticamente tipado? E que um dos frameworks mais populares do ecossistema Python, o FastAPI, se apoia totalmente nisso?

Vamos por partes.

O que são Type Hints?

Type hints (ou "dicas de tipo") são anotações que você adiciona ao código Python para indicar qual tipo de dado uma variável, parâmetro ou retorno de função deveria ter. Eles foram introduzidos na PEP 484 (Python 3.5+).

Sem type hints:

def somar(a, b):
    return a + b
Enter fullscreen mode Exit fullscreen mode

Com type hints:

def somar(a: int, b: int) -> int:
    return a + b
Enter fullscreen mode Exit fullscreen mode

O detalhe crucial: o Python NÃO impede você de passar uma string ali. Ele continua sendo dinamicamente tipado. Os type hints são apenas anotações. Quem realmente usa essas anotações são ferramentas externas como o mypy, o Pyright e, claro, o FastAPI.

E o que o FastAPI faz com isso?

O FastAPI é um framework web moderno para construir APIs em Python. Ele usa os type hints para:

  • Validar automaticamente os dados de entrada
  • Serializar/deserializar JSON
  • Gerar documentação interativa (Swagger UI) sem esforço

Exemplo prático:

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Usuario(BaseModel):
    nome: str
    idade: int
    email: str

@app.post("/usuarios")
def criar_usuario(usuario: Usuario):
    return {"msg": f"Bem-vindo, {usuario.nome}!"}
Enter fullscreen mode Exit fullscreen mode

Só com essas anotações de tipo, o FastAPI já sabe que se alguém mandar {"nome": "Felipe", "idade": "abc", "email": "f@x.com"}, ele vai rejeitar a request porque "abc" não é um int. E a documentação interativa já aparece pronta em /docs. Tudo isso vem de graça pelos type hints.

O grande tema: tipagem dinâmica vs. estática

As linguagens de programação costumam ser classificadas assim:

  • Estaticamente tipadas: os tipos são verificados em tempo de compilação. Se tem erro de tipo, o código nem compila. Exemplos: Java, C, C++, Go, Rust.
  • Dinamicamente tipadas: os tipos só são verificados em tempo de execução. Você pode atribuir qualquer valor a qualquer variável. Exemplos: Python, JavaScript, Ruby, PHP.

Mas essa fronteira ficou muito borrada nos últimos anos. E é aí que fica interessante.

Linguagens estáticas que "parecem" dinâmicas

Java com var (Java 10+):

var nome = "Felipe";       // o compilador infere que é String
var lista = List.of(1, 2); // infere List<Integer>
Enter fullscreen mode Exit fullscreen mode

Continua estático! O tipo é inferido em compilação, você só não precisa escrever ele explicitamente. Se tentar fazer nome = 42 depois, não compila.

Kotlin com val/var:

val idade = 25  // Int inferido
val nome = "Felipe"  // String inferido
Enter fullscreen mode Exit fullscreen mode

Go com :=:

nome := "Felipe"  // string inferido
idade := 25       // int inferido
Enter fullscreen mode Exit fullscreen mode

C++ com auto:

auto x = 3.14;  // double inferido
auto s = std::string("hello");
Enter fullscreen mode Exit fullscreen mode

Em todos esses casos, a tipagem continua sendo estática e rígida. O compilador resolve o tipo sozinho por inferência. Mas visualmente, o código parece tão "solto" quanto Python.

Linguagens dinâmicas que "parecem" estáticas

Python com type hints:

def buscar(id: int) -> dict[str, str]:
    ...
Enter fullscreen mode Exit fullscreen mode

JavaScript com TypeScript:

let nome: string = "Felipe";
let idade: number = 25;

function somar(a: number, b: number): number {
    return a + b;
}
Enter fullscreen mode Exit fullscreen mode

TypeScript é o exemplo mais radical disso. Ele adiciona uma camada inteira de tipagem estática sobre o JavaScript, mas no final tudo é compilado de volta para JS puro (sem tipos).

PHP com type declarations (PHP 7+):

function somar(int $a, int $b): int {
    return $a + $b;
}
Enter fullscreen mode Exit fullscreen mode

Ruby com Sorbet/RBS:

# typed: strict
sig {params(nome: String, idade: Integer).returns(String)}
def saudacao(nome, idade)
  "Olá, #{nome}! Você tem #{idade} anos."
end
Enter fullscreen mode Exit fullscreen mode

O espectro, não a caixa

A verdade é que "dinâmica vs. estática" não é mais uma classificação binária. É um espectro:

  1. Lado estático puro: C, Rust, Haskell
  2. Estático com inferência forte: Kotlin, Go, Swift
  3. Tipagem gradual: TypeScript, Python + mypy, PHP 7+
  4. Dinâmico com anotações opcionais: Ruby + Sorbet
  5. Lado dinâmico puro: JavaScript vanilla, Lua

O movimento é claro: linguagens dinâmicas estão adotando mecanismos de tipagem estática, e linguagens estáticas estão ficando mais ergonômicas com inferência de tipos. Ambos os lados estão caminhando para o meio.

E o Python, com seus type hints, está no coração desse movimento. Frameworks como o FastAPI provam que essas anotações não são só "decoração". Elas alimentam validação, documentação e tooling real.

Se você trabalha com Python e ainda não usa type hints, vale muito a pena começar. Seu editor vai te agradecer, seu time vai te agradecer, e o FastAPI vai fazer mágica com eles.

Top comments (0)