Optional Types
Optional Types
Section titled “Optional Types”PyGo provides explicit nullability handling through the Type? syntax. Unlike Python’s None, which can be ambiguous (is it a missing value or an intentionally unset value?), PyGo’s Type? makes nullability explicit, compile-time checked, and transpiled consistently to both Go and Python.
Basic Usage
Section titled “Basic Usage”model User: name: String nickname: String? # Optional (nullable), defaults to None age: Int? # Optional (nullable), no default updated: DateTime? # Optional DateTimeOptional vs Default
Section titled “Optional vs Default”model User: # This field MUST be provided (not nullable) name: String
# This field can be null, defaults to None nickname: String?
# This field can be null, must be explicitly provided age: Int?
# This field has a default value but is NOT nullable status: String = "active"Generated Code
Section titled “Generated Code”Go:
type User struct { Name string // not nullable Nickname *string // pointer for nullable (Optional) Age *int // pointer for nullable (Optional) Status string // not nullable, has default Updated *time.Time // pointer for nullable DateTime}Python:
from typing import Optionalfrom datetime import datetime
class User(BaseModel): name: str nickname: Optional[str] = None age: Optional[int] status: str = "active" updated: Optional[datetime] = NoneDatabase Representation
Section titled “Database Representation”CREATE TABLE user ( id INTEGER PRIMARY KEY, name TEXT NOT NULL, nickname TEXT, -- NULL allowed (String?) age INTEGER, -- NULL allowed (Int?) status TEXT NOT NULL -- NULL not allowed (String = "active"));Optional with Complex Types
Section titled “Optional with Complex Types”model Profile: tags: Array[String]? # Optional array metadata: Map[String, String]? # Optional map config: Config? # Optional model referenceValidation
Section titled “Validation”Optional fields are validated at compile time:
user = User(name="Alice", age=30)
# Valid — age is Int?, 30 is an Intuser.age = 31
# Valid — setting to None is always valid for Optional typesuser.age = NoneBest Practices
Section titled “Best Practices”- Use
Type?explicitly when a field can be null - Use
Type(without?) when a field must always have a value - Always provide sensible defaults for optional fields where possible
- Use
String?rather thanString = Nonefor clarity - Prefer
?syntax overOptional[T]for new projects
Migration from Earlier Versions
Section titled “Migration from Earlier Versions”# Old style (still supported, but not recommended)name: Optional[String]
# New style (recommended)name: String?Both generate the same code — Go *T and Python Optional[T].