9  Type Hint: Evolution

Source: https://youtu.be/RwH2UzC2rIo?si=dJwlRhTjOlAx6lQ7

9.1 Type Alias

type RGB = tuple[int, int, int]
type TripleInt = tuple[int, int, int]
RGB == TripleInt
False
type User = dict[str, str | int | None]
def create_user(first_name: str, last_name: str, age: int | None = None) -> User:
    email = f"{first_name.lower()}_{last_name[0:3].lower()}@example.com"
    return {
        "first_name": first_name,
        "last_name": last_name,
        "age": age,
        "email": email
    }
create_user("kittipos", "sirivong", None)
{'first_name': 'kittipos',
 'last_name': 'sirivong',
 'age': None,
 'email': 'kittipos_sir@example.com'}

9.2 NewType

from typing import NewType
RGB = NewType("RGB", tuple[int, int, int]) 
HSL = NewType("HSL", tuple[int, int, int]) 

type User = dict[str, str | int | None | RGB]
def create_user(first_name: str, last_name: str, age: int | None = None, fav_color: RGB | None = None) -> User:
    email = f"{first_name.lower()}_{last_name[0:3].lower()}@example.com"
    return {
        "first_name": first_name,
        "last_name": last_name,
        "age": age,
        "email": email,
        "fav_color": fav_color
    }
create_user("kittipos", "sirivong", None, RGB((122, 334, 433)))
{'first_name': 'kittipos',
 'last_name': 'sirivong',
 'age': None,
 'email': 'kittipos_sir@example.com',
 'fav_color': (122, 334, 433)}
# Will warn wrong type
create_user("kittipos", "sirivong", None, HSL((122, 334, 433)))
{'first_name': 'kittipos',
 'last_name': 'sirivong',
 'age': None,
 'email': 'kittipos_sir@example.com',
 'fav_color': (122, 334, 433)}

9.3 TypedDict

from typing import TypedDict

class User(TypedDict):
    first_name: str
    last_name: str
    age: int | None
    email: str
    fav_color: RGB | None
def create_user(first_name: str, last_name: str, age: int | None = None, fav_color: RGB | None = None) -> User:
    email = f"{first_name.lower()}_{last_name[0:3].lower()}@example.com"
    return {
        "first_name": first_name,
        "last_name": last_name,
        "age": str(age), # Wrong type
        "email": email,
        "fav_color": fav_color
    }

9.4 DataClass

from dataclasses import dataclass
@dataclass
class User:
    first_name: str
    last_name: str
    email: str
    age: int | None = None
    fav_color: RGB | None = None
def create_user(
    first_name: str,
    last_name: str,
    age: int | None = None,
    fav_color: RGB | None = None,
) -> User:
    email = f"{first_name.lower()}_{last_name[0:3].lower()}@example.com"
    return User(
        first_name=first_name,
        last_name=last_name,
        email=email,
        age=age,
        fav_color=fav_color,
    )
create_user("kittipos", "sirivong", None, RGB((122, 334, 433)))
User(first_name='kittipos', last_name='sirivong', email='kittipos_sir@example.com', age=None, fav_color=(122, 334, 433))

9.5 Generic Type (TypeVar)

from typing import TypeVar
import random
T = TypeVar("T")

def random_choice(items: list[T]) -> T:
    return random.choice(items)

# Or

def random_choice2[T](items: list[T]) -> T:
    return random.choice(items)
user1 = create_user("kittipos", "sirivong", None, RGB((122, 334, 433)))
user2 = create_user("lightbridge", "ks", None, RGB((122, 334, 433)))
random_choice([user1, user2])
User(first_name='lightbridge', last_name='ks', email='lightbridge_ks@example.com', age=None, fav_color=(122, 334, 433))
random_choice([user1.email, user2.email])
'kittipos_sir@example.com'