Skip to content
Maarten Vroegindeweij edited this page Feb 18, 2026 · 1 revision

@ifc-factory/schema

Layer 2 — Auto-generated IFC4X3 ADD2 TypeScript types. No runtime dependencies. Generated files are committed to the repository for IDE support and faster builds.

Installation

pnpm add @ifc-factory/schema

Usage

Import Types

import type {
  IfcWall,
  IfcDoor,
  IfcWindow,
  IfcProject,
  IfcSite,
  IfcBuilding,
  IfcBuildingStorey,
  IfcPropertySet,
  IfcRelAggregates,
} from '@ifc-factory/schema';

Use Runtime Metadata

import { SCHEMA_METADATA, ENTITY_REGISTRY } from '@ifc-factory/schema';

// Look up entity metadata
const wallMeta = SCHEMA_METADATA['IfcWall'];
console.log(`Parent: ${wallMeta.parent}`);           // 'IfcBuildingElement'
console.log(`Abstract: ${wallMeta.abstract}`);       // false
console.log(`Attributes: ${wallMeta.allAttributes.length}`);  // 9

// List all attributes including inherited
for (const attr of wallMeta.allAttributes) {
  console.log(`  ${attr.name}: ${attr.type} ${attr.optional ? '(optional)' : ''}`);
}
// GlobalId: string
// OwnerHistory: ref (optional)
// Name: string (optional)
// Description: string (optional)
// ObjectType: string (optional)
// ObjectPlacement: ref (optional)
// Representation: ref (optional)
// Tag: string (optional)
// PredefinedType: enum (optional)

// Resolve STEP uppercase name to TypeScript name
const typeName = ENTITY_REGISTRY['IFCWALL'];  // 'IfcWall'
const typeName2 = ENTITY_REGISTRY['IFCBUILDINGSTOREY'];  // 'IfcBuildingStorey'

Use Base Types

import type { IfcGenericEntity } from '@ifc-factory/schema';

// IfcGenericEntity is the base type for all entities
function processEntity(entity: IfcGenericEntity) {
  console.log(`#${entity.expressID}: ${entity.type}`);

  // Access any attribute dynamically
  if ('Name' in entity) {
    console.log(`  Name: ${entity['Name']}`);
  }
}

Check Entity Inheritance

import { SCHEMA_METADATA } from '@ifc-factory/schema';

function getInheritanceChain(entityType: string): string[] {
  const chain = [entityType];
  let meta = SCHEMA_METADATA[entityType];
  while (meta?.parent) {
    chain.unshift(meta.parent);
    meta = SCHEMA_METADATA[meta.parent];
  }
  return chain;
}

console.log(getInheritanceChain('IfcWall'));
// ['IfcRoot', 'IfcObjectDefinition', 'IfcObject', 'IfcProduct',
//  'IfcElement', 'IfcBuildingElement', 'IfcWall']

// Check if an entity type is a subtype of another
function isSubtypeOf(entityType: string, parentType: string): boolean {
  return getInheritanceChain(entityType).includes(parentType);
}

console.log(isSubtypeOf('IfcWall', 'IfcProduct'));  // true
console.log(isSubtypeOf('IfcWall', 'IfcDoor'));     // false

Find All Subtypes

import { SCHEMA_METADATA } from '@ifc-factory/schema';

function getAllSubtypes(parentType: string): string[] {
  const subtypes: string[] = [];
  for (const [name, meta] of Object.entries(SCHEMA_METADATA)) {
    if (meta.parent === parentType) {
      subtypes.push(name);
      subtypes.push(...getAllSubtypes(name));
    }
  }
  return subtypes;
}

// All concrete building elements
const buildingElements = getAllSubtypes('IfcBuildingElement');
console.log(buildingElements);
// ['IfcWall', 'IfcDoor', 'IfcWindow', 'IfcSlab', 'IfcColumn', 'IfcBeam', ...]

Schema Statistics

Generated from IFC4X3 ADD2 EXPRESS schema (IFC4X3_DEV_923b0514):

Category Count
Entity interfaces 876
Enumerations 243
Type aliases 132
Select (union) types 61
Schema metadata entries 876
Entity registry entries 876
Total generated lines ~12,000+

Key Types

IfcGenericEntity

The base interface for all IFC entities:

interface IfcGenericEntity {
  expressID: number;         // Unique entity identifier (#N in STEP)
  type: string;              // Entity type name (e.g., 'IfcWall')
  [key: string]: unknown;    // Dynamic attribute access
}

EntityMetadata

Runtime metadata for each entity type:

interface EntityMetadata {
  parent: string | null;             // Parent entity type name
  abstract: boolean;                 // Can this type be instantiated?
  allAttributes: AttributeMetadata[];  // All attributes in STEP order
}

interface AttributeMetadata {
  name: string;      // Attribute name (e.g., 'GlobalId')
  type: string;      // Attribute type (e.g., 'string', 'ref', 'enum')
  optional: boolean; // Is this attribute optional?
}

ENTITY_REGISTRY

Maps STEP uppercase type names to TypeScript PascalCase names:

const ENTITY_REGISTRY: Record<string, string> = {
  'IFCACTORROLE': 'IfcActorRole',
  'IFCADDRESS': 'IfcAddress',
  'IFCWALL': 'IfcWall',
  // ... 876 entries
};

Entity Inheritance Tree (excerpt)

IfcRoot (abstract)
├── IfcObjectDefinition (abstract)
│   ├── IfcObject (abstract)
│   │   ├── IfcProduct (abstract)
│   │   │   ├── IfcElement (abstract)
│   │   │   │   ├── IfcBuildingElement (abstract)
│   │   │   │   │   ├── IfcWall
│   │   │   │   │   ├── IfcWallStandardCase
│   │   │   │   │   ├── IfcDoor
│   │   │   │   │   ├── IfcWindow
│   │   │   │   │   ├── IfcSlab
│   │   │   │   │   ├── IfcColumn
│   │   │   │   │   ├── IfcBeam
│   │   │   │   │   ├── IfcRoof
│   │   │   │   │   ├── IfcStair
│   │   │   │   │   ├── IfcRailing
│   │   │   │   │   ├── IfcCovering
│   │   │   │   │   ├── IfcCurtainWall
│   │   │   │   │   ├── IfcPlate
│   │   │   │   │   └── ...
│   │   │   │   ├── IfcDistributionElement
│   │   │   │   │   └── IfcDistributionFlowElement
│   │   │   │   │       ├── IfcFlowSegment
│   │   │   │   │       ├── IfcFlowTerminal
│   │   │   │   │       └── ...
│   │   │   │   ├── IfcFurnishingElement
│   │   │   │   └── IfcTransportationDevice
│   │   │   ├── IfcSpatialElement (abstract)
│   │   │   │   ├── IfcSpatialStructureElement (abstract)
│   │   │   │   │   ├── IfcSite
│   │   │   │   │   ├── IfcBuilding
│   │   │   │   │   ├── IfcBuildingStorey
│   │   │   │   │   └── IfcSpace
│   │   │   │   ├── IfcSpatialZone
│   │   │   │   └── IfcExternalSpatialElement
│   │   │   └── IfcAnnotation
│   │   ├── IfcProcess (abstract)
│   │   ├── IfcResource (abstract)
│   │   └── IfcActor
│   ├── IfcContext (abstract)
│   │   ├── IfcProject
│   │   └── IfcProjectLibrary
│   └── IfcTypeObject
│       └── IfcTypeProduct
│           └── IfcElementType
│               └── IfcBuildingElementType
│                   ├── IfcWallType
│                   ├── IfcDoorType
│                   └── ...
├── IfcRelationship (abstract)
│   ├── IfcRelAggregates
│   ├── IfcRelContainedInSpatialStructure
│   ├── IfcRelDefinesByProperties
│   ├── IfcRelAssociatesMaterial
│   ├── IfcRelAssociatesDocument
│   ├── IfcRelAssociatesClassification
│   ├── IfcRelAssociatesLibrary
│   └── ...
└── IfcPropertyDefinition (abstract)
    ├── IfcPropertySet
    ├── IfcElementQuantity
    └── IfcPropertySetTemplate

Regenerating the Schema

When the IFC EXPRESS schema is updated:

# 1. Replace the schema file
cp new-schema.exp schemas/IFC4X3_ADD2.exp

# 2. Regenerate TypeScript
pnpm build:schema

# 3. Verify
pnpm build && pnpm test

This runs:

tsx packages/codegen/src/cli.ts schemas/IFC4X3_ADD2.exp packages/schema/src/generated/

See Also

  • codegen — The code generator that produces this package
  • step-parser — Uses schema metadata for typed parsing
  • IFC Concepts — Background on IFC entity hierarchy

Clone this wiki locally