mypy — Type Hints Cheat Sheet
Contoh cepat untuk hampir setiap pola anotasi tipe yang muncul di kode Python sehari-hari.
Intisari
- Halaman ini untuk dilihat sekilas saat menulis kode, bukan dibaca berurutan. Bookmark-lah.
- Pola paling sering: koleksi,
| None,Callable,Literal, generic. TypeVaruntuk fungsi yang mempertahankan tipe input di outputnya.Protocol= duck typing yang bisa dicek — “apa pun yang punya method ini”.reveal_type(x)membuat mypy mencetak tipe yang ia simpulkan. Alat debug tipe terbaik.
Variabel
x: int = 1
y: str # dideklarasikan, belum diisi
z: list[int] = []
# Biasanya tidak perlu — mypy bisa menyimpulkan sendiri
umur = 30 # mypy tahu ini int
Anotasi variabel hanya perlu saat mypy tidak bisa menebak, misalnya list kosong.
Fungsi
def sapa(nama: str) -> str: ...
def cetak(pesan: str) -> None: ... # tidak mengembalikan apa-apa
def gagal(pesan: str) -> NoReturn: ... # selalu melempar exception
def konfigurasi(
host: str,
port: int = 8000,
*args: str, # sisa argumen posisional
debug: bool = False, # setelah *: wajib bernama
**opsi: str, # sisa argumen bernama
) -> None: ...
Koleksi
a: list[str]
b: dict[str, int]
c: set[str]
d: tuple[int, str] # persis dua elemen
e: tuple[int, ...] # berapa pun elemen int
from collections.abc import Sequence, Iterable, Iterator, Mapping, Callable
def f(items: Sequence[str]) -> None: ... # list ATAU tuple
def g(items: Iterable[str]) -> None: ... # apa pun yang bisa di-for
def h(m: Mapping[str, int]) -> None: ... # dict, read-only
Opsional dan union
nilai: str | None = None
campur: int | str | None
def cari(id: str) -> Dokumen | None: ...
Menyempitkan union
def proses(x: int | str) -> str:
if isinstance(x, int):
return str(x) # di sini mypy tahu x adalah int
return x.upper() # di sini mypy tahu x adalah str
def pakai(d: Dokumen | None) -> str:
if d is None:
return ""
return d.judul # aman: mypy tahu d bukan None
Class
class Dokumen:
judul: str # atribut tingkat class
_cache: dict[str, str] = {}
def __init__(self, judul: str, isi: str = "") -> None:
self.judul = judul
self.isi = isi
def ringkas(self, panjang: int = 100) -> str:
return self.isi[:panjang]
@classmethod
def dari_json(cls, data: dict) -> "Dokumen": ...
@staticmethod
def valid(teks: str) -> bool: ...
@property
def jumlah_kata(self) -> int:
return len(self.isi.split())
Generator dan async
from collections.abc import Iterator, AsyncIterator, Awaitable
def baca(path: str) -> Iterator[str]:
yield "baris"
async def ambil(url: str) -> dict: ...
async def stream(url: str) -> AsyncIterator[str]:
yield "potongan"
def nanti() -> Awaitable[str]: ... # sesuatu yang bisa di-await
Literal dan Final
from typing import Literal, Final
Mode = Literal["fast", "accurate"]
def jalankan(mode: Mode = "fast") -> None: ...
jalankan("cepat") # error: Argument has incompatible type
MAX_TOKENS: Final = 4096 # mypy melarang perubahan nilai ini
TypeVar — generic
def pertama[T](items: list[T]) -> T | None: # sintaks Python 3.12+
return items[0] if items else None
pertama([1, 2, 3]) # mypy tahu hasilnya int | None
pertama(["a", "b"]) # mypy tahu hasilnya str | None
# Sintaks lama, masih umum ditemui
from typing import TypeVar
T = TypeVar("T")
def pertama(items: list[T]) -> T | None: ...
Protocol — duck typing yang bisa dicek
from typing import Protocol
class PunyaEmbedding(Protocol):
def embed(self, teks: str) -> list[float]: ...
def indeks(model: PunyaEmbedding, docs: list[str]) -> None:
for d in docs:
model.embed(d)
Class apa pun yang punya method embed dengan tanda tangan itu akan diterima —
tanpa perlu mewarisi apa pun. Ini cara mengetikkan "duck typing" yang biasa dipakai Python,
dan sangat pas untuk menukar implementasi asli dengan versi palsu saat testing.
TypedDict — dict dengan bentuk tetap
from typing import TypedDict
class Pesan(TypedDict):
role: str
content: str
msg: Pesan = {"role": "user", "content": "halo"} # dicek mypy
Berguna untuk struktur seperti messages di API LLM yang memang harus berupa dict.
Debugging tipe
reveal_type(hasil) # mypy mencetak tipe yang ia simpulkan, lalu error di baris itu
note: Revealed type is "builtins.list[myapp.Dokumen]"
Jangan lupa hapus setelah selesai — reveal_type tidak ada saat runtime dan akan
menyebabkan NameError kalau tertinggal.
Membungkam error
x = fungsi_aneh() # type: ignore[no-any-return]
from typing import cast
d = cast(Dokumen, data_mentah) # "percaya aku, ini Dokumen"
Referensi ke depan
from __future__ import annotations # taruh di baris pertama file
class Node:
def anak(self) -> list[Node]: ... # boleh menyebut Node meski belum selesai didefinisikan
Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.