Skip to main content

Overview

tif1 is built with type safety as a first-class citizen. Every public API, function, method, and data structure includes comprehensive type hints that enable static type checkers (mypy, pyright, pytype) to catch errors before runtime. This design philosophy provides multiple benefits:
  • Compile-time error detection: Catch type mismatches, invalid parameters, and API misuse before running code
  • Enhanced IDE support: Get accurate autocomplete, inline documentation, parameter hints, and refactoring tools
  • Self-documenting code: Type hints serve as inline documentation that never goes out of sync
  • Safer refactoring: Change code with confidence knowing type checkers will catch breaking changes
  • Better developer experience: Spend less time debugging runtime errors and more time building features
This comprehensive guide covers all type definitions available in tif1, organized into the following sections:

What You’ll Learn

  1. Literal Type Aliases - Constrained string values for session types, tire compounds, backends, and track status
  2. TypedDict Schemas - Structured definitions for DataFrame row data (laps, telemetry, weather, race control)
  3. DataFrame Type Hints - Proper typing for pandas and polars DataFrames
  4. Object Type Hints - Type annotations for Session, Driver, Lap, and other core objects
  5. Protocol Types - Duck-typed interfaces for DataFrame-like objects
  6. Generic Type Patterns - Advanced patterns for async functions, unions, and generic code
  7. Type Checking Tools - How to use mypy, pyright, and IDE integrations
  8. Best Practices - Proven patterns for writing type-safe tif1 code

Quick Import Reference

All types are importable from tif1.types:

Type System Philosophy

tif1 follows these type system principles:
  1. Explicit over implicit: All public APIs have explicit type annotations
  2. Strict by default: Types are as specific as possible (Literal types over str)
  3. Optional transparency: Optional fields use NotRequired or Optional to make None handling explicit
  4. Backend agnostic: Union types support both pandas and polars without code changes
  5. Runtime validation: Types are validated at runtime where appropriate (pydantic models)
  6. Zero runtime cost: Type hints have no performance impact in production

Literal Type Aliases

Literal types are one of Python’s most powerful type system features. They restrict values to a specific, finite set of allowed strings, providing compile-time validation and excellent autocomplete support in IDEs. Unlike plain str types, Literal types give you:
  • Exhaustive checking: Type checkers can verify all possible values are handled
  • Autocomplete: IDEs show exactly which values are valid
  • Refactoring safety: Renaming a literal value updates all usages
  • Documentation: The type itself documents valid values

BackendType

The BackendType literal specifies which DataFrame library backend to use for data operations. tif1 is designed to be backend-agnostic, supporting both pandas and polars with identical APIs.

Backend Comparison

When to Choose Each Backend

Choose pandas when:
  • Working with datasets under 1GB
  • Using existing pandas-based code or libraries
  • Need maximum ecosystem compatibility (scikit-learn, matplotlib, etc.)
  • Prefer familiar, widely-documented APIs
  • Doing interactive exploratory analysis in Jupyter
Choose polars when:
  • Working with datasets over 1GB
  • Need maximum performance and memory efficiency
  • Building production data pipelines
  • Want lazy evaluation and query optimization
  • Need better multi-core utilization
  • Prefer strongly-typed, consistent APIs

Basic Usage

Global Configuration

Set the backend globally to avoid passing lib to every function:

Function Parameter Typing

Use BackendType in function signatures to enforce valid backends:

Runtime Backend Detection

Check which backend is being used at runtime:

Backend-Specific Optimizations

Write code that adapts to the backend:

Type-Safe Backend Switching

Create a utility to safely switch backends:

SessionType

The SessionType literal defines all valid Formula 1 session types across different weekend formats. Formula 1 has evolved its weekend structure over the years, introducing sprint races and varying qualifying formats. This type ensures you only reference sessions that actually exist in the F1 calendar.

F1 Weekend Format Evolution

Formula 1 weekend formats have changed significantly, especially with the introduction of sprint races: Standard Race Weekend (Traditional Format) Used for most Grand Prix weekends: Sprint Weekend Format (2021-2022) Introduced in 2021, modified the traditional format: Sprint Weekend Format (2023+) Current sprint format with additional qualifying:

Session Type Details

Practice Sessions
  • "Practice 1": First practice session, typically Friday morning
  • "Practice 2": Second practice session, typically Friday afternoon
  • "Practice 3": Third practice session, typically Saturday morning (standard weekends only)
Qualifying Sessions
  • "Qualifying": Main qualifying session determining race grid
  • "Sprint Qualifying": Qualifying for sprint race (2023 format, some races)
  • "Sprint Shootout": Alternative name for sprint qualifying (2023 format, some races)
Race Sessions
  • "Sprint": Short-format race (~100km, ~30 minutes)
  • "Race": Main Grand Prix race (full distance, ~305km except Monaco)

Basic Usage

Loading All Weekend Sessions

Iterate through all sessions for a complete weekend analysis:

Dynamic Session Detection

Handle different weekend formats automatically:

Weekend Format Detection

Determine which format a weekend uses:

Session Validation

Validate session names before using them:

Session Comparison and Analysis

Compare sessions across a weekend:

CompoundType

The CompoundType literal defines all possible tire compound names used in Formula 1. Pirelli, the official tire supplier, provides different compounds for different track conditions and strategies.

Tire Compound Breakdown

Dry Weather Compounds (Slick Tires) Pirelli brings three dry compounds to each race, designated as Soft, Medium, and Hard. The actual compounds vary by track:
  • "SOFT": Fastest but least durable, used for qualifying and short stints
    • Highest grip level
    • Fastest lap times
    • Shortest lifespan (typically 15-25 laps depending on track)
    • Preferred for qualifying and sprint races
    • Red sidewall marking
  • "MEDIUM": Balanced performance and durability
    • Middle ground between speed and longevity
    • Common race start tire
    • Moderate degradation (typically 25-35 laps)
    • Yellow sidewall marking
  • "HARD": Slowest but most durable, used for long stints
    • Lowest grip but longest lifespan
    • Used for one-stop strategies
    • Highest durability (typically 35-50+ laps)
    • White sidewall marking
Wet Weather Compounds (Grooved Tires)
  • "INTERMEDIATE": For damp or drying track conditions
    • Used when track is wet but not soaked
    • Can disperse moderate water
    • Green sidewall marking
    • Often used as track transitions from wet to dry
  • "WET": For heavy rain and standing water
    • Maximum water displacement (85 liters per second at 300 km/h)
    • Deep grooves for aquaplaning prevention
    • Blue sidewall marking
    • Mandatory in very wet conditions
Special Cases
  • "UNKNOWN": Compound data not available or not recorded
  • "TEST_UNKNOWN": Used during testing sessions where compound is not specified

Basic Usage

Tire Strategy Analysis

Analyze tire strategies across a race:

Compound Performance Comparison

Compare lap times across different compounds:

Tire Degradation Analysis

Track tire degradation over a stint:

Compound Usage Statistics

Get overall compound usage statistics:

TrackStatusType

The TrackStatusType literal defines track status codes that indicate race control conditions during a session. These codes are critical for understanding when laps are valid for comparison and when incidents occurred.

Track Status Breakdown

Green Flag Conditions
  • "1": Normal racing conditions
    • Full racing speed allowed
    • Overtaking permitted
    • Lap times are representative
    • Used for performance analysis
Yellow Flag Conditions
  • "2": Local yellow flag
    • Danger on or near track
    • Drivers must slow down
    • No overtaking in affected sector
    • Lap times affected, not representative
Safety Car Conditions
  • "4": Safety Car deployed
    • Physical pace car on track
    • All cars bunch up behind safety car
    • Significantly slower lap times
    • Used for major incidents or debris
    • Pit stops often strategic during SC
Virtual Safety Car
  • "6": VSC active
    • No physical car, drivers follow delta time
    • Must maintain specific lap time
    • No overtaking
    • Less bunching than full SC
    • Used for minor incidents
  • "7": VSC ending
    • Transition period
    • Drivers prepare to resume racing
    • Brief status before green flag
Red Flag
  • "5": Session stopped
    • All cars must return to pits
    • Track conditions unsafe
    • Used for major accidents, heavy rain, or track damage
    • Session may resume later

Basic Usage

Filtering Representative Laps

Get only laps that are representative of true pace:

Track Status Timeline

Analyze when track status changed during a session:

Safety Car Impact Analysis

Analyze the impact of safety cars on race pace:

TypedDict Schemas

TypedDict is a Python feature that provides type hints for dictionary structures. Unlike regular dictionaries, TypedDict allows you to specify:
  • Exact keys that must or may exist
  • Type of value for each key
  • Which fields are required vs optional
tif1 uses TypedDict extensively to define the structure of DataFrame row data. This provides:
  • Type safety: IDEs and type checkers know what fields exist
  • Autocomplete: Get field suggestions when accessing row data
  • Documentation: The type itself documents the data structure
  • Validation: Catch typos and missing fields at development time
All TypedDict schemas use NotRequired for optional fields, making it explicit which fields may be None or missing.

LapDataDict

The LapDataDict TypedDict defines the complete structure of lap timing data in DataFrames. This is the most comprehensive data structure in tif1, containing timing, speed, tire, weather, and metadata for each lap.

Field Categories Explained

Core Identity Fields These four fields are always present and form the unique identity of each lap:
Lap Timing Fields Timing data uses datetime.timedelta objects for precision and easy arithmetic:
Speed Trap Fields Speed measurements at various points around the track (in km/h):
Tire Information Fields Track tire compound, age, and condition:
Session/Lap Metadata Fields Additional context about the lap:
Per-Lap Weather Fields Weather conditions sampled at each lap:

Complete Lap Analysis Example

Comprehensive example using all field categories:

TelemetryDataDict

Structure of high-frequency telemetry data. All fields except Time are optional.
Usage:

WeatherDataDict

Structure of weather data returned by session.weather.
Usage:

RaceControlDataDict

Structure of race control messages.
Usage:

DriverInfoDict

Structure of driver information.
Usage:

DataFrame type hints

For better IDE support, use type hints with DataFrames:

Pandas DataFrames

Polars DataFrames

Union types for lib-agnostic code


Object type hints

Core Objects

Model Objects


Generic type hints

Async Functions

Dictionary Returns


Complete type-annotated example


Type Checking

Using mypy

Using pyright

IDE Support

Modern IDEs like VS Code, PyCharm, and others provide:
  • Autocomplete based on type hints
  • Inline type checking
  • Parameter hints
  • Return type hints
Example in VS Code:

Best Practices

  1. Always use type hints in function signatures: Helps catch errors early.
  2. Use Union types for lib-agnostic code: Supports both pandas and polars.
  3. Import types from tif1.types: Centralized type definitions.
  4. Use TypedDict for JSON data: Better than plain dicts.
  5. Enable strict type checking: Use mypy or pyright in CI/CD.
  6. Document complex types: Add docstrings explaining type parameters.
  7. Use Optional for nullable values: Makes None handling explicit.
“Belgian Grand Prix”, “Race”)

Hovering over ‘session’ shows: session: Session

laps = session.laps

Hovering over ‘laps’ shows: laps: DataFrame

driver = session.get_driver(“VER”)

Hovering over ‘driver’ shows: driver: Driver

2. Use Union Types for Backend-Agnostic Code

Support both pandas and polars without code duplication:

3. Import Types from tif1.types

Centralized type definitions ensure consistency:

4. Use TypedDict for Structured Data

Better than plain dicts for type safety:

5. Enable Strict Type Checking

Use mypy or pyright in your development workflow:

6. Document Complex Types

Add docstrings explaining type parameters:

7. Use Optional for Nullable Values

Make None handling explicit:

8. Leverage Type Guards

Use type guards for runtime type checking:

9. Use Literal Types for Constants

Restrict values to specific constants:

10. Combine Types for Complex Scenarios

Use type combinations for advanced patterns:

Summary

This comprehensive guide covered all type definitions in tif1:

Key Takeaways

  1. Literal Types provide compile-time validation for constrained values (BackendType, SessionType, CompoundType, TrackStatusType)
  2. TypedDict Schemas define structured DataFrame row data with explicit required/optional fields (LapDataDict, TelemetryDataDict, WeatherDataDict, RaceControlDataDict, DriverInfoDict)
  3. DataFrame Types support both pandas and polars through Union types, enabling backend-agnostic code
  4. Object Types provide type hints for core tif1 objects (Session, Driver, Lap, Telemetry)
  5. Type Checking Tools (mypy, pyright) catch errors before runtime and integrate with modern IDEs
  6. Best Practices include always using type hints, leveraging Union types, importing from tif1.types, and enabling strict type checking

Benefits of Type Safety in tif1

  • Catch Errors Early: Type checkers find bugs before code runs
  • Better IDE Support: Autocomplete, inline docs, refactoring tools
  • Self-Documenting: Types serve as always-current documentation
  • Safer Refactoring: Change code confidently with type validation
  • Improved Collaboration: Types communicate intent to other developers
  • Zero Runtime Cost: Type hints have no performance impact

Next Steps

  1. Enable Type Checking: Add mypy or pyright to your project
  2. Add Type Hints: Annotate your tif1 code with proper types
  3. Use IDE Features: Leverage autocomplete and inline documentation
  4. Write Type-Safe Code: Follow the best practices outlined above
  5. Contribute: Help improve tif1’s type definitions
For more information, see:
Last modified on May 8, 2026