| name | ifc-syntax-data-types |
| description | Use when you need to pick or read the value type of an IFC attribute or property : which measure type a length, area, or volume needs, when to use IfcLabel vs IfcText vs IfcIdentifier, IfcBoolean vs IfcLogical, and how a typed value is wrapped in a STEP file. Prevents storing a quantity under the wrong measure type, exceeding the 255-character string cap, collapsing a three-valued logical into a boolean, and writing a bare value where a select type requires a TYPENAME() wrapper. Covers the IfcValue / IfcSimpleValue / IfcMeasureValue / IfcDerivedMeasureValue select hierarchy, the measure types, string and identity types, the USERDEFINED / NOTDEFINED enumeration convention, refinement WHERE rules, and IFC2x3 / IFC4 / IFC4.3 version differences. Keywords: IFC data types, IfcValue, IfcSimpleValue, IfcMeasureValue, IfcDerivedMeasureValue, IfcLengthMeasure, IfcAreaMeasure, IfcVolumeMeasure, IfcLabel, IfcText, IfcIdentifier, IfcBoolean, IfcLogical, measure type, typed value wrapping, USERDEFINED, NOTDEFINED, ObjectType, what type should this value be, wrong units in my model, my area is off by 1000x, string too long, how do I store a property value, IFC2x3, IFC4, IFC4.3.
|
| license | MIT |
| compatibility | Designed for Claude Code. Requires IFC IFC2x3, IFC4, IFC4.3. |
| metadata | {"author":"OpenAEC-Foundation","version":"1.0"} |
IFC Syntax : Data Types
This skill answers one concrete question : what can the value of an IFC attribute or
property hold, and how is that value typed in a file? It covers IFC's own resource-
layer value-type system : the named defined types (IfcLengthMeasure, IfcLabel,
IfcBoolean, ...) and the SELECT unions that group them.
Applies to IFC2x3, IFC4, and IFC4.3. Member lists differ by version : see the
Version Differences section.
Quick Reference
Two type systems : keep them apart
IFC has two layered type systems. ALWAYS keep them separate :
- The EXPRESS meta-language (
ifc-syntax-express) : the constructs TYPE,
ENTITY, SELECT, ENUMERATION, the base types STRING, REAL, INTEGER,
BOOLEAN, LOGICAL, BINARY, NUMBER. These are the blocks the schema is
written with.
- IFC's own value-type system (this skill) : the named defined types IFC
declares on top of those base types, plus the
SELECT unions that group them.
IFC wraps every base type in a named defined type because an EXPRESS SELECT may
list only named types, NEVER raw BOOLEAN / REAL / INTEGER. That is why
TYPE IfcBoolean = BOOLEAN;, TYPE IfcReal = REAL;, and TYPE IfcInteger = INTEGER;
exist : so they can be members of a select.
IfcValue : the two-level union
IfcValue is the most general value type in IFC. It is the declared type of
IfcPropertySingleValue.NominalValue and of IfcMeasureWithUnit.ValueComponent.
Verified verbatim (IFC4.3, introduced IFC2x) :
TYPE IfcValue = SELECT
(IfcDerivedMeasureValue
,IfcMeasureValue
,IfcSimpleValue);
END_TYPE;
IfcValue is a SELECT whose three members are themselves SELECT types : a
two-level union. A parser resolving an IfcValue descends through one branch to
reach a concrete defined type.
| Branch | Holds | Has a unit? |
|---|
IfcSimpleValue | primitive, dimensionless values : booleans, integers, reals, strings, logicals, dates, binary | No |
IfcMeasureValue | base physical measures : length, area, volume, angle, mass, count, ratio | Yes (single SI dimension) |
IfcDerivedMeasureValue | compound measures : force, pressure, velocity, density, thermal transmittance, money | Yes (derived SI dimension) |
IfcSimpleValue members (IFC4.3 : 15 members)
| Type | Base | Use for |
|---|
IfcBoolean | BOOLEAN | a known two-valued yes/no fact |
IfcLogical | LOGICAL | a fact that may also be UNKNOWN |
IfcInteger | INTEGER | whole numbers |
IfcPositiveInteger | INTEGER, SELF > 0 | strictly positive whole numbers (IFC4+) |
IfcReal | REAL | dimensionless real numbers |
IfcLabel | STRING(255) | a human-readable name |
IfcText | STRING (unbounded) | free-form description / note |
IfcIdentifier | STRING(255) | a machine-readable code / key |
IfcBinary | BINARY | embedded binary data, for example textures (IFC4 ADD1+) |
IfcDateTime | STRING, ISO 8601 | date and time (IFC4+) |
IfcDate | STRING, ISO 8601 | calendar date (IFC4+) |
IfcTime | STRING, ISO 8601 | time of day (IFC4+) |
IfcDuration | STRING, ISO 8601 | a duration (IFC4+) |
IfcTimeStamp | INTEGER | seconds since the Unix epoch |
IfcURIReference | STRING | a URI / URL / URN (IFC4+) |
IfcMeasureValue : high-frequency base measures (IFC4.3 : 23 members)
| Measure type | Base | Unit type implied |
|---|
IfcLengthMeasure | REAL | LENGTHUNIT |
IfcPositiveLengthMeasure | IfcLengthMeasure, SELF > 0 | LENGTHUNIT |
IfcNonNegativeLengthMeasure | IfcLengthMeasure, SELF >= 0 (IFC4+) | LENGTHUNIT |
IfcAreaMeasure | REAL | AREAUNIT |
IfcVolumeMeasure | REAL | VOLUMEUNIT |
IfcPlaneAngleMeasure | REAL | PLANEANGLEUNIT |
IfcMassMeasure | REAL | MASSUNIT |
IfcCountMeasure | INTEGER (IFC4.3 ; NUMBER before) | not a unit type |
IfcRatioMeasure | REAL | dimensionless |
IfcNormalisedRatioMeasure | IfcRatioMeasure, 0.0 <= SELF <= 1.0 | dimensionless |
Full 23-member list : see references/methods.md.
IfcDerivedMeasureValue : high-frequency derived measures (IFC4.3 : 70 members)
| Measure type | Base | Notes |
|---|
IfcForceMeasure | REAL | force |
IfcPressureMeasure | REAL | pressure |
IfcLinearVelocityMeasure | REAL | velocity |
IfcMassDensityMeasure | REAL | density |
IfcThermalTransmittanceMeasure | REAL | U-value |
IfcMonetaryMeasure | REAL | money, currency-agnostic |
IfcCompoundPlaneAngleMeasure | LIST [3:4] OF INTEGER | degrees / minutes / seconds, NOT a scalar |
Full 70-member list : see references/methods.md.
Typed-value wrapping in a STEP file
A value whose attribute is declared with a concrete type is written bare :
'Wall-01' for an IfcLabel-typed Name.
A value whose attribute is declared as a SELECT (such as IfcValue) MUST be
wrapped in the upper-cased name of the concrete member type, so the reader knows
which branch was chosen :
#101=IFCPROPERTYSINGLEVALUE('FireRating',$,IFCLABEL('REI 60'),$);
#102=IFCPROPERTYSINGLEVALUE('NetArea',$,IFCAREAMEASURE(12.5),$);
#103=IFCPROPERTYSINGLEVALUE('LoadBearing',$,IFCBOOLEAN(.T.),$);
The wrapper name IS the type tag. NEVER write a bare value where a select type is
expected : the reader cannot tell 12.5 apart as an area, a length, or a plain real.
Version differences (compact)
| Item | IFC2x3 | IFC4 | IFC4.3 |
|---|
IfcSimpleValue members | 7 | 15 | 15 |
IfcDateTime, IfcDate, IfcTime, IfcDuration, IfcBinary, IfcPositiveInteger, IfcURIReference | absent | present | present |
IfcCountMeasure base type | NUMBER | NUMBER | INTEGER |
IfcNonNegativeLengthMeasure | absent | present | present |
IfcLabel / IfcIdentifier 255 cap | recommended | mandatory | mandatory |
Decision Trees
Which value type for a property value?
What does the value represent?
|
+-- A physical quantity with a single SI dimension
| (length, area, volume, angle, mass, ratio, count)
| --> IfcMeasureValue branch. Pick the measure type whose
| dimension matches : IfcLengthMeasure, IfcAreaMeasure, ...
|
+-- A compound physical quantity
| (force, pressure, velocity, density, U-value, money)
| --> IfcDerivedMeasureValue branch.
| IfcForceMeasure, IfcPressureMeasure, IfcMonetaryMeasure, ...
|
+-- A non-physical, dimensionless value
(text, name, code, yes/no, count of items, date, real number)
--> IfcSimpleValue branch. IfcLabel, IfcText, IfcBoolean, ...
IfcBoolean or IfcLogical?
Can the attribute meaningfully be "unknown / not applicable",
distinct from FALSE?
|
+-- NO : it is always a known yes/no fact
| --> IfcBoolean (.T. / .F.)
|
+-- YES : "not known" is a real third state
--> IfcLogical (.T. / .F. / .U.)
NEVER substitute IfcBoolean for a schema-declared IfcLogical :
that collapses UNKNOWN into FALSE and loses information.
A present .U. is NOT the same as an absent $ (unset OPTIONAL).
IfcLabel, IfcText, or IfcIdentifier?
What is the string for?
|
+-- A short, human-readable display NAME
| --> IfcLabel (STRING(255))
|
+-- A machine-readable CODE / KEY, stable and locale-independent
| (classification code, part number)
| --> IfcIdentifier (STRING(255))
|
+-- Free-form descriptive prose, a note, possibly long
--> IfcText (unbounded STRING)
IfcLabel and IfcIdentifier are byte-identical (STRING(255)) but
NEVER interchangeable in intent : the schema picks one deliberately.
Which measure type for a quantity?
Match the measure type to the physical SI dimension :
|
+-- a distance --> IfcLengthMeasure
+-- a distance, > 0 --> IfcPositiveLengthMeasure
+-- a distance, >= 0 --> IfcNonNegativeLengthMeasure (IFC4+)
+-- a surface area --> IfcAreaMeasure
+-- a volume --> IfcVolumeMeasure
+-- a planar angle --> IfcPlaneAngleMeasure
+-- a latitude/longitude--> IfcCompoundPlaneAngleMeasure (deg/min/sec list)
+-- a mass --> IfcMassMeasure
+-- a count of items --> IfcCountMeasure
+-- a same-kind ratio --> IfcRatioMeasure (percent / 100)
+-- a ratio in [0,1] --> IfcNormalisedRatioMeasure
NEVER pick by what parses : an area stored as IfcLengthMeasure
parses fine and resolves to the wrong project unit.
Patterns
Pattern : Wrap select-typed values
ALWAYS wrap a value as TYPENAME(value) when the attribute is declared as a SELECT
(such as IfcValue, IfcSizeSelect, IfcUnit). The wrapper is the discriminator.
ALWAYS write a value bare when the attribute is declared with a concrete defined type :
IfcRoot.Name is IfcLabel, so 'Wall-01' is written bare.
NEVER write a bare numeric or string value into a select-typed attribute : the reader
has no way to know which select member it is, and the file is malformed.
See ifc-syntax-step-physical-file for the full STEP instance syntax.
Pattern : Pick the measure type by SI dimension
ALWAYS choose the measure type whose physical dimension matches the quantity : a
length is IfcLengthMeasure, an area is IfcAreaMeasure, a volume is
IfcVolumeMeasure, an angle is IfcPlaneAngleMeasure.
The measure type, NOT the number, selects the unit. An IfcLengthMeasure of 3.5
means 3.5 of the project length unit. A wall area stored as IfcLengthMeasure
resolves against LENGTHUNIT instead of AREAUNIT and silently corrupts every
downstream quantity take-off.
NEVER decide a measure type by whether the value parses : every measure type is
ultimately a REAL, so a wrong type always parses.
See ifc-syntax-units for how a unit type resolves to a concrete unit.
Pattern : Choose two-valued vs three-valued logic
ALWAYS use IfcLogical when "unknown" or "not applicable" is a meaningful state
distinct from FALSE. The canonical case is IfcMaterialLayer.IsVentilated, an
OPTIONAL IfcLogical : TRUE is a ventilated air gap, FALSE is solid material,
UNKNOWN is a non-ventilated air gap.
ALWAYS use IfcBoolean when the attribute is a yes/no fact that is always known.
NEVER treat a present IfcLogical value of .U. (UNKNOWN) as equivalent to an
absent OPTIONAL attribute ($) : $ means no value was supplied, .U. means a
value was supplied and it is the third logical state.
Pattern : Pair USERDEFINED with ObjectType
Almost every IFC PredefinedType enumeration (for example IfcWallTypeEnum) ends
with two special members : USERDEFINED and NOTDEFINED. NOTDEFINED means no
predefined type applies. USERDEFINED means a type outside the fixed list.
ALWAYS supply the paired free-text type name when PredefinedType = USERDEFINED :
on an occurrence object, in IfcObject.ObjectType (an IfcLabel) ; on a type
object, in IfcElementType.ElementType. An entity WHERE rule (for example
IfcWall.CorrectPredefinedType) enforces this pairing.
NEVER set PredefinedType = USERDEFINED and leave the paired attribute unset : the
file violates the WHERE rule and is schema-invalid.
An enumeration value is NOT an IfcValue. IfcValue covers user-supplied data
values ; a PredefinedType is a schema-fixed classification token. They are
different layers. See ifc-syntax-express for the ENUMERATION construct.
Pattern : Respect refinement WHERE rules
The Positive*, NonNegative*, and Normalised* types are NOT separate primitive
types : they are defined types layered on a base measure with an added WHERE rule.
| Type | Base | WHERE rule |
|---|
IfcPositiveLengthMeasure | IfcLengthMeasure | SELF > 0. |
IfcNonNegativeLengthMeasure | IfcLengthMeasure | SELF >= 0. |
IfcPositivePlaneAngleMeasure | IfcPlaneAngleMeasure | SELF > 0. |
IfcPositiveRatioMeasure | IfcRatioMeasure | SELF > 0. |
IfcNormalisedRatioMeasure | IfcRatioMeasure | {0.0 <= SELF <= 1.0} |
ALWAYS check the refinement's WHERE rule before assigning : 0.0 or a negative
value in an IfcPositiveLengthMeasure parses as a plain real but is schema-invalid.
NEVER assume a value that parses satisfies the type : the WHERE rule is part of the
type.
Pattern : Honour version differences
ALWAYS target the member list for the file's declared schema version :
- In IFC2x3,
IfcSimpleValue has only 7 members. NEVER emit IfcDateTime,
IfcDate, IfcTime, IfcDuration, IfcBinary, IfcPositiveInteger, or
IfcURIReference as an IfcValue payload in an IFC2x3 file : IFC2x3 uses
structured date entities (IfcCalendarDate, IfcLocalTime, IfcDateAndTime).
- In IFC4.3,
IfcCountMeasure is an INTEGER. A non-integer count is valid
IFC4 but invalid IFC4.3. ALWAYS use whole numbers for IfcCountMeasure in IFC4.3.
- The
IfcLabel / IfcIdentifier 255-character cap was advisory before IFC4 and
mandatory from IFC4 onward.
See references/methods.md for the complete per-version member tables.
Reference Links
references/methods.md : the complete verified member lists : IfcSimpleValue
(15 + the IFC2x3 7), the full 23-member IfcMeasureValue select, the full
70-member IfcDerivedMeasureValue select, every base definition, the measure-to-
unit-type mapping, and the per-version difference tables.
references/examples.md : worked scenarios : typing a property value, reading a
wrapped STEP value, choosing between string types, USERDEFINED pairing,
IFC2x3-vs-IFC4 value typing.
references/anti-patterns.md : the failure modes this skill prevents, each with
the reason it fails.
Official sources
Related skills
ifc-syntax-express : the EXPRESS meta-language : TYPE, SELECT, ENUMERATION,
WHERE, the base types this skill's defined types are built on.
ifc-syntax-units : how a measure type's unit type resolves to a concrete unit
via IfcUnitAssignment.
ifc-syntax-property-sets : where IfcValue-typed property values are carried.