Skip to content

Type-Safe Development

idfkit ships auto-generated type stubs for all 858 EnergyPlus object types. Your IDE gets autocomplete, inline documentation, and error detection out of the box — no plugins or configuration needed.

Differs in Python

Static types generated from the schema exists in both libraries and does not behave the same way in Python. The ledger records it as Python partial, JavaScript complete, and what differs is stated here rather than left to be discovered.

Coverage differs, and the difference is visible to anyone not on the newest release. The Python stub set is generated for one EnergyPlus version at a time and is currently shipped for 26.1.0 only, so a model loaded at 9.4 gets the 26.1 field names and choice lists from the editor. The TypeScript type maps are emitted per version and selected by the caller, who parameterises the document with the map for the version being read, so an older model is typed as that older model or is left untyped rather than mistyped.

Application differs too. Python's stubs apply implicitly to every document. TypeScript's are opt-in by construction: an unparameterised document stays untyped, which is what version-generic code needs.

The full entry, including the vocabulary this capability owns, is on the capability parity page.

IDE Autocomplete and Inline Docs

Every object type has a typed attribute accessor on IDFDocument and typed fields on individual objects. Your IDE will show field names, types (including Literal for enumerated choices), docstrings with units, defaults, and valid ranges.

from idfkit import load_idf

model = load_idf("building.idf")

# Typed accessor — returns IDFCollection[Zone]
zones = model.zones

# O(1) lookup by name — returns Zone (typed IDFObject subclass)
zone = zones["Office"]

# Field access with IDE autocomplete and type info
print(zone.x_origin)  # float | None
print(zone.multiplier)  # int | None

# Subscript access also works
all_zones = model["Zone"]

For example, hovering over zone.ceiling_height in your IDE will show:

(property) ceiling_height: float | Literal["", "Autocalculate"] | None

Strict Field Access

By default, accessing a misspelled field name raises an InvalidFieldError. Disable strict mode to fall back to returning None for unknown fields:

from idfkit import new_document

# Strict field access is on by default
doc = new_document()

zone = doc.add("Zone", "Office")
zone.x_origin = 0.0  # OK — valid field

# zone.x_orgin = 0.0  # InvalidFieldError! Typo caught immediately

# Also the default when loading files
# model = load_idf("building.idf")
# model = load_epjson("building.epJSON")
Function Parameter
new_document() strict=True (default)
load_idf() strict=True (default)
load_epjson() strict=True (default)

Tip

Strict mode is on by default. Disable it with strict=False when loading third-party IDF files that may contain non-standard fields.

Dynamic Key Access

When the object type is a string literal, doc["Zone"] returns a fully typed collection. When the key comes from a variable, use get_collection() to get a safely typed IDFCollection[IDFObject]:

# Literal key — fully typed, IDE knows the return type
zones = model["Zone"]

# Dynamic key — use get_collection() for variable object types
obj_type = "Zone"
collection = model.get_collection(obj_type)  # IDFCollection[IDFObject]

Use doc["Zone"] when you know the type at write time. Use doc.get_collection(obj_type) in generic functions that accept any object type.

Why get_collection()?

Under the hood, doc["Zone"] is typed via a TypedDict with all 858 EnergyPlus object types as literal keys. This gives your type checker exact return types for each key — but TypedDict subscript access requires string literals, so a plain str variable won't type-check. An @overload-based approach was considered but rejected because 858 overloads cause significant performance degradation in pyright. get_collection() is the lightweight escape hatch: it accepts any str and returns the base IDFCollection[IDFObject] type.

Version Availability

Type stubs include "Since: X.Y.Z" annotations in docstrings for object types and fields that were introduced after EnergyPlus 8.9.0. This helps you avoid using features that don't exist in your target version:

from idfkit import new_document

doc = new_document(version=(25, 2, 0))

# SpaceHVAC:ZoneReturnMixer was added in EnergyPlus 24.2.0
# IDE docstring shows: "Since: 24.2.0"
mixer = doc.add("SpaceHVAC:ZoneReturnMixer", "Return Mixer 1")
mixer.zone_name = "Office"

Hovering over SpaceHVACZoneReturnMixer in your IDE shows the docstring including "Since: 24.2.0", making it clear which minimum EnergyPlus version is required.

See Also