Code Review · Python

Python Code Review: Missing Type Hints

Review Python code where missing type hints make the function contract unclear.

Code Review Exercise

Review the following Python function. The code works for the happy path, but it is harder to understand and easier to misuse than it needs to be.

python
def apply_discount(order, discount):
    total = 0

    for item in order["items"]:
        total += item["price"] * item["quantity"]

    if discount:
        total = total - discount

    return round(total, 2)

What issues would you mention in a code review?

Review Findings

Issue #1: The input shape is unclear

The function expects order to be a dictionary with an items key. Each item is also expected to containprice and quantity. None of that is obvious from the function signature.

Issue #2: The discount type is ambiguous

Is discount a number, percentage, coupon object, string code, or nullable value? Without type hints, callers have to inspect the implementation or guess.

Issue #3: Truthiness can hide valid values

The check if discount: treats 0,None, and other falsy values the same way. If those values have different meanings, this can become a correctness bug.

Issue #4: Missing return type

The function returns a rounded number, but the signature does not say whether callers should expect an int,float, Decimal, or something else.

Why Type Hints Help In Review

Type hints are not only for type checkers. In interviews and real code reviews, they make the contract of a function easier to see.

A reviewer can quickly answer:

  • What input shape does this function expect?
  • Can a value be None?
  • What does the function return?
  • Is a dictionary the right model, or should this be a class/dataclass?

Better Version With Type Hints

python
from typing import TypedDict


class OrderItem(TypedDict):
    price: float
    quantity: int


class Order(TypedDict):
    items: list[OrderItem]


def apply_discount(order: Order, discount: float | None = None) -> float:
    total = 0.0

    for item in order["items"]:
        total += item["price"] * item["quantity"]

    if discount is not None:
        total -= discount

    return round(total, 2)

This version makes the expected structure visible. It also separatesNone from numeric values like 0.

Even Better Design Option

If this logic grows, a dictionary may not be the best model. A dataclass can make the domain clearer.

python
from dataclasses import dataclass


@dataclass(frozen=True)
class OrderItem:
    price: float
    quantity: int


@dataclass(frozen=True)
class Order:
    items: list[OrderItem]


def apply_discount(order: Order, discount: float | None = None) -> float:
    total = sum(item.price * item.quantity for item in order.items)

    if discount is not None:
        total -= discount

    return round(total, 2)

This may be overkill for a tiny script, but it is often cleaner in application code where the data shape matters.

What Not To Do

Do not turn every small script into a type-heavy design exercise. The goal is not to add ceremony everywhere.

A good review comment is balanced:

The function depends on a specific dictionary shape, but the signature does not show that. Consider adding type hints or a small dataclass if this is production code.

Interview Follow-Ups

Do Python type hints affect runtime behavior?

Usually no. Type hints are mainly for readability, IDE support, static analysis, and tools like mypy or pyright. Python does not enforce them by default at runtime.

When are type hints most useful?

They are especially useful at module boundaries, public functions, service methods, data models, and places where the input shape is not obvious.

Should every local variable have a type hint?

No. Over-annotating simple local variables can add noise. Function parameters, return types, and complex data structures are usually more valuable.

What is the difference between TypedDict and dataclass?

TypedDict describes the expected shape of a dictionary. A dataclass creates an actual class with named fields. TypedDict is useful when dictionaries are already part of the interface; dataclasses are often cleaner for domain objects.

What Interviewers Expect

A strong code review answer should not simply say, “add type hints.” Explain why they matter here.

  • The input structure is hidden.
  • The discount contract is unclear.
  • The return type is not obvious.
  • The code may benefit from TypedDict or a dataclass.
  • Do not add unnecessary ceremony for tiny throwaway scripts.