Skip to content
Sarj Code Standards

prefer-typed-settings-field

Declare numeric model domains and use typed choices for token-valued defaults.

Why

Bare model numbers omit their valid domain; raw token defaults hide a choice or identifier domain. A primitive annotation can also erase an enum, nominal identifier or URL contract demonstrated by its default.

Fix

Reuse the default's enum or NewType, use a Pydantic URL type with the accepted schemes, and prefer PositiveInt/NonNegativeInt or PositiveFloat/NonNegativeFloat for exact zero bounds. Keep units, aliases and source precedence explicit. Use SecretStr for secrets, existing domain identifiers, nested settings with default_factory, declarative bounds and pure computed properties where their contracts justify them. Validate textual environment values; do not enable blanket strict mode or change coercion, optionality or startup behavior without checking real environment inputs.

Examples

Before — flagged A primitive annotation erases an enum default
app/settings.py
from enum import StrEnum
from pydantic import Field
from pydantic_settings import BaseSettings
class Mode(StrEnum):
CLOUD = "cloud"
class Settings(BaseSettings):
mode: str = Field(default=Mode.CLOUD, alias="MODE")
After — preferred The field retains its domain type
app/settings.py
from enum import StrEnum
from pydantic import Field
from pydantic_settings import BaseSettings
class Mode(StrEnum):
CLOUD = "cloud"
class Settings(BaseSettings):
mode: Mode = Field(default=Mode.CLOUD, alias="MODE")
Before — flagged A measurement has no declared numeric domain
app/models.py
from pydantic import BaseModel
class Audio(BaseModel):
duration_seconds: float
After — preferred The model declares a positive measurement
app/models.py
from pydantic import BaseModel, PositiveFloat
class Audio(BaseModel):
duration_seconds: PositiveFloat
Before — flagged A raw token default does not declare its domain
app/settings.py
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
voice: str = "voice_a"
After — preferred A closed token default retains its enum domain
app/settings.py
from enum import StrEnum
from pydantic_settings import BaseSettings
class Voice(StrEnum):
MAIN = "voice_a"
class Settings(BaseSettings):
voice: Voice = Voice.MAIN