# Ifc Syntax Data Types

> 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, ObjectT

- Skill: `impertio-studio/ifc-syntax-data-types` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add impertio-studio/ifc-syntax-data-types`
- Raw SKILL.md: https://api.skillmd.com/api/skills/impertio-studio/ifc-syntax-data-types/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: MIT
- Author: Impertio-Studio (https://skillmd.com/u/impertio-studio)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/impertio-studio/ifc-syntax-data-types

---


# 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 :

1. **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.
2. **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

- IfcValue : https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcValue.htm
- IfcSimpleValue : https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcSimpleValue.htm
- IfcMeasureValue : https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcMeasureValue.htm
- IfcDerivedMeasureValue : https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcDerivedMeasureValue.htm
- IFC2x3 IfcSimpleValue : https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/ifcmeasureresource/lexical/ifcsimplevalue.htm

### 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.

