Type System

Loading concept...

FastAPI Type System: Your Magic Labels 🏷️

Imagine you have a toy box. What if every toy had a special label telling you exactly what it is? A car label, a doll label, a ball label. You’d never get confused!

In FastAPI, type hints are those magic labels. They tell Python (and you!) exactly what kind of data you’re working with.


The Big Picture

Think of types like sorting bins in a classroom:

  • One bin for numbers (age, price, count)
  • One bin for words (names, messages)
  • One bin for yes/no answers (is it raining?)

Python’s type system helps you put the right things in the right bins!


1. Python Type Hints

What Are They?

Type hints are like name tags for your data. They tell everyone what kind of information a variable holds.

name: str = "Emma"
age: int = 8
height: float = 4.2
is_happy: bool = True

Plain English:

  • str = words and sentences (strings)
  • int = whole numbers (integers)
  • float = numbers with decimals
  • bool = True or False only

In FastAPI

from fastapi import FastAPI

app = FastAPI()

@app.get("/hello/{name}")
def say_hello(name: str):
    return {"message": f"Hello, {name}!"}

The : str tells FastAPI: “This name must be text!”

graph TD A[User sends name] --> B{Is it text?} B -->|Yes| C[✅ Works!] B -->|No| D[❌ Error message]

2. Union and Optional Types

The “Either/Or” Label

Sometimes a toy can be more than one thing. A transformer can be a car OR a robot!

from typing import Union

price: Union[int, float] = 9.99
# price can be 10 OR 10.50

The “Maybe” Label (Optional)

What if a field might be empty? Like a nickname - not everyone has one!

from typing import Optional

nickname: Optional[str] = None
# Same as: Union[str, None]

Real FastAPI Example

from typing import Union, Optional

@app.get("/items/{item_id}")
def get_item(
    item_id: int,
    name: Optional[str] = None,
    price: Union[int, float] = 0
):
    return {
        "id": item_id,
        "name": name,
        "price": price
    }

What happens:

  • item_id: MUST be a number
  • name: Can be text OR nothing
  • price: Can be whole number OR decimal

3. Annotated Type Hints

Super-Powered Labels!

Annotated lets you add extra instructions to your labels. Like a toy label that also says “batteries included!”

from typing import Annotated
from fastapi import Query

@app.get("/search")
def search(
    q: Annotated[str, Query(min_length=3)]
):
    return {"query": q}

What this means:

  • q must be text (str)
  • AND it must be at least 3 characters long!

More Examples

from typing import Annotated
from fastapi import Path, Query

@app.get("/users/{user_id}")
def get_user(
    user_id: Annotated[int, Path(gt=0)],
    limit: Annotated[int, Query(le=100)] = 10
):
    return {"user_id": user_id, "limit": limit}
Parameter Type Extra Rule
user_id int Must be > 0
limit int Must be ≤ 100
graph TD A[Annotated] --> B[Base Type] A --> C[Extra Rules] B --> D[str, int, etc.] C --> E[min_length] C --> F[gt, lt, ge, le] C --> G[regex patterns]

4. Date and Time Types

Clock Labels!

Python has special types for dates and times. Like having a calendar bin and a clock bin!

from datetime import date, time, datetime
from datetime import timedelta

birthday: date = date(2016, 5, 15)
# Just the day: 2016-05-15

alarm: time = time(7, 30, 0)
# Just the clock: 07:30:00

party: datetime = datetime(2024, 12, 25, 18, 0)
# Day AND clock: 2024-12-25 18:00:00

wait: timedelta = timedelta(days=7)
# How long to wait: 7 days

In FastAPI

from datetime import date, datetime

@app.post("/events")
def create_event(
    name: str,
    event_date: date,
    created_at: datetime
):
    return {
        "name": name,
        "date": event_date,
        "created": created_at
    }

FastAPI automatically converts text like "2024-12-25" into a proper date!

Type Example What It Holds
date 2024-12-25 Year, month, day
time 14:30:00 Hour, minute, second
datetime 2024-12-25T14:30:00 Both!
timedelta 7 days Duration

5. Special Data Types

Fancy Labels for Fancy Data!

FastAPI has special types for common things:

UUID - Unique ID

from uuid import UUID

@app.get("/orders/{order_id}")
def get_order(order_id: UUID):
    return {"order": str(order_id)}

# Example: 550e8400-e29b-41d4-a716-446655440000

Like a fingerprint - every UUID is unique!

EmailStr - Valid Email

from pydantic import EmailStr

@app.post("/signup")
def signup(email: EmailStr):
    return {"email": email}

# âś… "emma@school.com" - Works!
# ❌ "not-an-email" - Error!

HttpUrl - Valid Web Address

from pydantic import HttpUrl

@app.post("/bookmark")
def save_bookmark(url: HttpUrl):
    return {"saved": str(url)}

# âś… "https://example.com" - Works!
# ❌ "not-a-url" - Error!
graph TD A[Special Types] --> B[UUID] A --> C[EmailStr] A --> D[HttpUrl] B --> E[Unique IDs] C --> F[Valid Emails] D --> G[Valid URLs]

6. Enum Types

The “Pick One” Label!

Sometimes you can only choose from a fixed list. Like picking your favorite color from red, blue, or green - nothing else allowed!

from enum import Enum

class Color(str, Enum):
    red = "red"
    blue = "blue"
    green = "green"

favorite: Color = Color.red

In FastAPI

from enum import Enum

class Size(str, Enum):
    small = "small"
    medium = "medium"
    large = "large"

@app.get("/shirts/{size}")
def get_shirt(size: Size):
    return {"size": size}

# âś… /shirts/small - Works!
# âś… /shirts/medium - Works!
# ❌ /shirts/huge - Error!

Why Use Enums?

Without Enum With Enum
User types “smol” Only “small” allowed
Typos cause bugs No typos possible
Hard to remember options Clear list of choices
graph TD A[User picks size] --> B{Is it in the list?} B -->|small/medium/large| C[✅ Accepted] B -->|anything else| D[❌ Rejected]

Integer Enums

Numbers can be enums too!

from enum import IntEnum

class Priority(IntEnum):
    low = 1
    medium = 2
    high = 3

@app.post("/tasks")
def create_task(priority: Priority):
    return {"priority": priority}

Putting It All Together

Here’s a complete example using everything we learned:

from fastapi import FastAPI, Query
from typing import Annotated, Optional
from datetime import datetime
from enum import Enum
from pydantic import EmailStr
from uuid import UUID

app = FastAPI()

class Status(str, Enum):
    pending = "pending"
    done = "done"

@app.post("/tasks")
def create_task(
    title: str,
    email: EmailStr,
    status: Status = Status.pending,
    due_date: Optional[datetime] = None,
    priority: Annotated[
        int, Query(ge=1, le=5)
    ] = 3
):
    return {
        "title": title,
        "email": email,
        "status": status,
        "due": due_date,
        "priority": priority
    }

Quick Reference

Type Use For Example
str Text “Hello”
int Whole numbers 42
float Decimals 3.14
bool Yes/No True
Optional[X] Maybe empty None or value
Union[A, B] Either type int or str
Annotated Extra rules min_length, gt
date Calendar day 2024-12-25
datetime Day + time 2024-12-25T10:00
Enum Fixed choices small/medium/large
UUID Unique ID 550e8400-…
EmailStr Valid email a@b.com

You Did It! 🎉

You now understand FastAPI’s type system! Remember:

  • Type hints = Labels for your data
  • Optional/Union = Flexible labels
  • Annotated = Labels with extra rules
  • Date/Time = Calendar and clock labels
  • Enums = Pick-from-a-list labels

These labels make your API safer, clearer, and easier to use!

Loading story...

No Story Available

This concept doesn't have a story yet.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

Interactive Preview

Interactive - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

No Interactive Content

This concept doesn't have interactive content yet.

Cheatsheet Preview

Cheatsheet - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

No Cheatsheet Available

This concept doesn't have a cheatsheet yet.

Quiz Preview

Quiz - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

No Quiz Available

This concept doesn't have a quiz yet.