diff --git a/src/language/ast/ASTNodeDataTypeBuilder.cpp b/src/language/ast/ASTNodeDataTypeBuilder.cpp
index 44e30ec2e11fba9db2701268d582089f9cb839f4..d8cf06824ea5cf070a07a84d4bf3bcc711f71a79 100644
--- a/src/language/ast/ASTNodeDataTypeBuilder.cpp
+++ b/src/language/ast/ASTNodeDataTypeBuilder.cpp
@@ -212,9 +212,16 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
 
         auto simple_type_allocator = [&](const ASTNode& type_node, ASTNode& symbol_node) {
           Assert(symbol_node.is_type<language::name>());
-          const ASTNodeDataType& data_type = type_node.m_data_type.contentType();
 
-          symbol_node.m_data_type   = type_node.m_data_type.contentType();
+          const ASTNodeDataType data_type = [&] {
+            if (type_node.m_data_type == ASTNodeDataType::type_id_t) {
+              return ASTNodeDataType::build<ASTNodeDataType::type_id_t>(type_node.m_data_type.nameOfTypeId());
+            } else {
+              return type_node.m_data_type.contentType();
+            }
+          }();
+
+          symbol_node.m_data_type   = data_type;
           const std::string& symbol = symbol_node.string();
 
           std::shared_ptr<SymbolTable>& symbol_table = n.m_symbol_table;
@@ -357,6 +364,8 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
           value_type = getMatrixDataType(image_node);
         } else if (image_node.is_type<language::string_type>()) {
           value_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
+        } else if (image_node.is_type<language::type_name_id>()) {
+          value_type = ASTNodeDataType::build<ASTNodeDataType::type_id_t>(image_node.m_data_type.nameOfTypeId());
         }
 
         // LCOV_EXCL_START
@@ -528,7 +537,14 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
 
         ASTNode& image_domain_node = *function_descriptor.domainMappingNode().children[1];
 
-        n.m_data_type = image_domain_node.m_data_type.contentType();
+        n.m_data_type = [&] {
+          if (image_domain_node.m_data_type == ASTNodeDataType::type_id_t) {
+            return ASTNodeDataType::build<ASTNodeDataType::type_id_t>(image_domain_node.m_data_type.nameOfTypeId());
+          } else {
+            return image_domain_node.m_data_type.contentType();
+          }
+        }();
+
       } else if (n.children[0]->m_data_type == ASTNodeDataType::builtin_function_t) {
         auto builtin_function_embedder = getBuiltinFunctionEmbedder(n);
 
diff --git a/src/language/ast/ASTNodeDataTypeFlattener.cpp b/src/language/ast/ASTNodeDataTypeFlattener.cpp
index a2f83e5923392163f54ccc1b8bdecd5b8ed96e86..7212d6b001a12de45e6b81e2955a80fe71cd07b4 100644
--- a/src/language/ast/ASTNodeDataTypeFlattener.cpp
+++ b/src/language/ast/ASTNodeDataTypeFlattener.cpp
@@ -30,8 +30,20 @@ ASTNodeDataTypeFlattener::ASTNodeDataTypeFlattener(ASTNode& node, FlattenedDataT
         ASTNode& function_image_domain = *function_descriptor.domainMappingNode().children[1];
 
         for (auto& image_sub_domain : function_image_domain.children) {
-          Assert(image_sub_domain->m_data_type == ASTNodeDataType::typename_t);
-          flattened_datatype_list.push_back({image_sub_domain->m_data_type.contentType(), node});
+          switch (image_sub_domain->m_data_type) {
+          case ASTNodeDataType::typename_t: {
+            flattened_datatype_list.push_back({image_sub_domain->m_data_type.contentType(), node});
+            break;
+          }
+          case ASTNodeDataType::type_id_t: {
+            flattened_datatype_list.push_back(
+              {ASTNodeDataType::build<ASTNodeDataType::type_id_t>(image_sub_domain->m_data_type.nameOfTypeId()), node});
+            break;
+          }
+          default: {
+            throw UnexpectedError("invalid data type");
+          }
+          }
         }
         break;
       }
diff --git a/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp b/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp
index 1fb23a5de3287b8b685ce9ef2ea4789697cbe198..15720a9f645616ad08588c5d00e5185d06482276 100644
--- a/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp
+++ b/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp
@@ -37,7 +37,29 @@ ASTNodeFunctionExpressionBuilder::_getArgumentConverter(SymbolType& parameter_sy
     }
       // LCOV_EXCL_START
     default: {
-      throw ParseError("unexpected error: invalid argument type 0",
+      throw ParseError("unexpected error: invalid argument type",
+                       std::vector{node_sub_data_type.m_parent_node.begin()});
+    }
+      // LCOV_EXCL_STOP
+    }
+  };
+
+  auto get_function_argument_converter_for_type_id =
+    [&](const std::string& type_id_name) -> std::unique_ptr<IFunctionArgumentConverter> {
+    switch (node_sub_data_type.m_data_type) {
+    case ASTNodeDataType::type_id_t: {
+      if (node_sub_data_type.m_data_type.nameOfTypeId() == type_id_name) {
+        return std::make_unique<FunctionArgumentConverter<EmbeddedData, EmbeddedData>>(parameter_id);
+      } else {
+        // LCOV_EXCL_START
+        throw ParseError("unexpected error: invalid argument type",
+                         std::vector{node_sub_data_type.m_parent_node.begin()});
+        // LCOV_EXCL_STOP
+      }
+    }
+      // LCOV_EXCL_START
+    default: {
+      throw ParseError("unexpected error: invalid argument type",
                        std::vector{node_sub_data_type.m_parent_node.begin()});
     }
       // LCOV_EXCL_STOP
@@ -181,6 +203,9 @@ ASTNodeFunctionExpressionBuilder::_getArgumentConverter(SymbolType& parameter_sy
       // LCOV_EXCL_START
       throw ParseError("unexpected error: undefined parameter type", std::vector{m_node.begin()});
       // LCOV_EXCL_STOP
+    }
+    case ASTNodeDataType::type_id_t: {
+      return get_function_argument_converter_for_type_id(parameter_symbol.attributes().dataType().nameOfTypeId());
     }
       // LCOV_EXCL_START
     default: {
@@ -377,6 +402,28 @@ ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType& r
     }
   };
 
+  auto get_function_processor_for_expression_type_id =
+    [&](const std::string& type_id_name) -> std::unique_ptr<INodeProcessor> {
+    switch (function_component_expression.m_data_type) {
+    case ASTNodeDataType::type_id_t: {
+      if (function_component_expression.m_data_type.nameOfTypeId() == type_id_name) {
+        return std::make_unique<FunctionExpressionProcessor<EmbeddedData, EmbeddedData>>(function_component_expression);
+      } else {
+        // LCOV_EXCL_START
+        throw ParseError("unexpected error: undefined expression value type for function",
+                         std::vector{node.children[1]->begin()});
+        // LCOV_EXCL_STOP
+      }
+    }
+      // LCOV_EXCL_START
+    default: {
+      throw ParseError("unexpected error: undefined expression value type for function",
+                       std::vector{node.children[1]->begin()});
+    }
+      // LCOV_EXCL_STOP
+    }
+  };
+
   auto get_function_processor_for_value = [&]() {
     switch (return_value_type) {
     case ASTNodeDataType::bool_t: {
@@ -439,6 +486,9 @@ ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType& r
     }
     case ASTNodeDataType::string_t: {
       return get_function_processor_for_expression_value(std::string{});
+    }
+    case ASTNodeDataType::type_id_t: {
+      return get_function_processor_for_expression_type_id(return_value_type.nameOfTypeId());
     }
       // LCOV_EXCL_START
     default: {
@@ -464,9 +514,19 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node
   std::unique_ptr function_processor = this->_buildArgumentConverter(function_descriptor, node);
 
   auto add_component_expression = [&](ASTNode& expression_node, const ASTNode& image_domain_node) {
-    Assert(image_domain_node.m_data_type == ASTNodeDataType::typename_t);
-
-    const ASTNodeDataType return_value_type = image_domain_node.m_data_type.contentType();
+    const ASTNodeDataType return_value_type = [&] {
+      switch (image_domain_node.m_data_type) {
+      case ASTNodeDataType::typename_t: {
+        return image_domain_node.m_data_type.contentType();
+      }
+      case ASTNodeDataType::type_id_t: {
+        return ASTNodeDataType::build<ASTNodeDataType::type_id_t>(image_domain_node.m_data_type.nameOfTypeId());
+      }
+      default: {
+        throw UnexpectedError("invalid function return type");
+      }
+      }
+    }();
 
     ASTNodeNaturalConversionChecker<AllowRToR1Conversion>{expression_node, return_value_type};
 
@@ -477,8 +537,19 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node
   ASTNode& function_image_domain = *function_descriptor.domainMappingNode().children[1];
   ASTNode& function_expression   = *function_descriptor.definitionNode().children[1];
 
-  Assert(function_image_domain.m_data_type == ASTNodeDataType::typename_t);
-  const ASTNodeDataType function_return_type = function_image_domain.m_data_type.contentType();
+  const ASTNodeDataType function_return_type = [&] {
+    switch (function_image_domain.m_data_type) {
+    case ASTNodeDataType::typename_t: {
+      return function_image_domain.m_data_type.contentType();
+    }
+    case ASTNodeDataType::type_id_t: {
+      return ASTNodeDataType::build<ASTNodeDataType::type_id_t>(function_image_domain.m_data_type.nameOfTypeId());
+    }
+    default: {
+      throw UnexpectedError("invalid function return type");
+    }
+    }
+  }();
 
   if (function_image_domain.is_type<language::vector_type>()) {
     ASTNodeDataType vector_type = getVectorDataType(function_image_domain);