diff --git a/src/query/backend/cpp/typed_value.cpp b/src/query/backend/cpp/typed_value.cpp
index 2574e43eb..084f728f3 100644
--- a/src/query/backend/cpp/typed_value.cpp
+++ b/src/query/backend/cpp/typed_value.cpp
@@ -12,32 +12,26 @@ TypedValue::TypedValue(const PropertyValue& value) {
     case PropertyValue::Type::Null:
       type_ = Type::Null;
       return;
-
     case PropertyValue::Type::Bool:
       type_ = Type::Bool;
       bool_v = value.Value<bool>();
       return;
-
     case PropertyValue::Type::Int:
       type_ = Type::Int;
       int_v = value.Value<int>();
       return;
-
     case PropertyValue::Type::Double:
       type_ = Type::Double;
       double_v = value.Value<double>();
-
     case PropertyValue::Type::String:
       type_ = Type::String;
       new (&string_v) std::string(value.Value<std::string>());
-
     case PropertyValue::Type::List:
       type_ = Type::List;
       auto vec = value.Value<std::vector<PropertyValue>>();
       new (&list_v) std::vector<TypedValue>(vec.begin(), vec.end());
       return;
   }
-
   permanent_fail("Unsupported PropertyValue::Type");
 }
 
@@ -56,6 +50,8 @@ TypedValue::operator PropertyValue() const {
     case TypedValue::Type::List:
       return PropertyValue(
           std::vector<PropertyValue>(list_v.begin(), list_v.end()));
+    default:
+      permanent_fail("Unsupported PropertyValue::Type");
   }
   permanent_fail("Unsupported PropertyValue::Type");
 }
@@ -68,13 +64,6 @@ bool TypedValue::Value<bool>() const {
   return bool_v;
 }
 
-template <>
-std::string TypedValue::Value<std::string>() const {
-  debug_assert(type_ == TypedValue::Type::String,
-               "Incompatible template param and type");
-  return string_v;
-}
-
 template <>
 int TypedValue::Value<int>() const {
   debug_assert(type_ == TypedValue::Type::Int,
@@ -89,6 +78,13 @@ double TypedValue::Value<double>() const {
   return double_v;
 }
 
+template <>
+std::string TypedValue::Value<std::string>() const {
+  debug_assert(type_ == TypedValue::Type::String,
+               "Incompatible template param and type");
+  return string_v;
+}
+
 template <>
 std::vector<TypedValue> TypedValue::Value<std::vector<TypedValue>>() const {
   debug_assert(type_ == TypedValue::Type::List,
@@ -96,32 +92,66 @@ std::vector<TypedValue> TypedValue::Value<std::vector<TypedValue>>() const {
   return list_v;
 }
 
+template <>
+std::map<std::string, TypedValue>
+TypedValue::Value<std::map<std::string, TypedValue>>() const {
+  debug_assert(type_ == TypedValue::Type::Map,
+               "Incompatible template param and type");
+  return map_v;
+}
+
+template <>
+VertexAccessor TypedValue::Value<VertexAccessor>() const {
+  debug_assert(type_ == TypedValue::Type::Vertex,
+               "Incompatible template param and type");
+  return vertex_v;
+}
+
+template <>
+EdgeAccessor TypedValue::Value<EdgeAccessor>() const {
+  debug_assert(type_ == TypedValue::Type::Edge,
+               "Incompatible template param and type");
+  return edge_v;
+}
+
+template <>
+Path TypedValue::Value<Path>() const {
+  debug_assert(type_ == TypedValue::Type::Path,
+               "Incompatible template param and type");
+  return path_v;
+}
+
 TypedValue::TypedValue(const TypedValue& other) : type_(other.type_) {
   switch (other.type_) {
     case TypedValue::Type::Null:
       return;
-
     case TypedValue::Type::Bool:
       this->bool_v = other.bool_v;
       return;
-
-    case TypedValue::Type::String:
-      new (&string_v) std::string(other.string_v);
-      return;
-
     case Type::Int:
       this->int_v = other.int_v;
       return;
-
     case Type::Double:
       this->double_v = other.double_v;
       return;
-
+    case TypedValue::Type::String:
+      new (&string_v) std::string(other.string_v);
+      return;
     case Type::List:
       new (&list_v) std::vector<TypedValue>(other.list_v);
       return;
+    case Type::Map:
+      new (&map_v) std::map<std::string, TypedValue>(other.map_v);
+      return;
+    case Type::Vertex:
+      new (&vertex_v) VertexAccessor(other.vertex_v);
+      return;
+    case Type::Edge:
+      new (&edge_v) EdgeAccessor(other.edge_v);
+      return;
+    case Type::Path:
+      new (&path_v) Path(other.path_v);
   }
-
   permanent_fail("Unsupported TypedValue::Type");
 }
 
@@ -131,14 +161,22 @@ std::ostream& operator<<(std::ostream& os, const TypedValue::Type type) {
       return os << "null";
     case TypedValue::Type::Bool:
       return os << "bool";
-    case TypedValue::Type::String:
-      return os << "string";
     case TypedValue::Type::Int:
       return os << "int";
     case TypedValue::Type::Double:
       return os << "double";
+    case TypedValue::Type::String:
+      return os << "string";
     case TypedValue::Type::List:
       return os << "list";
+    case TypedValue::Type::Map:
+      return os << "map";
+    case TypedValue::Type::Vertex:
+      return os << "vertex";
+    case TypedValue::Type::Edge:
+      return os << "edge";
+    case TypedValue::Type::Path:
+      return os << "path";
   }
   permanent_fail("Unsupported TypedValue::Type");
 }
@@ -149,18 +187,30 @@ std::ostream& operator<<(std::ostream& os, const TypedValue& value) {
       return os << "Null";
     case TypedValue::Type::Bool:
       return os << (value.Value<bool>() ? "true" : "false");
-    case TypedValue::Type::String:
-      return os << value.Value<std::string>();
     case TypedValue::Type::Int:
       return os << value.Value<int>();
     case TypedValue::Type::Double:
       return os << value.Value<double>();
+    case TypedValue::Type::String:
+      return os << value.Value<std::string>();
     case TypedValue::Type::List:
       os << "[";
       for (const auto& x : value.Value<std::vector<TypedValue>>()) {
         os << x << ",";
       }
       return os << "]";
+    case TypedValue::Type::Map:
+      os << "{";
+      for (const auto& x : value.Value<std::map<std::string, TypedValue>>()) {
+        os << x.first << ": " << x.second << ",";
+      }
+      return os << "}";
+    case TypedValue::Type::Vertex:
+      return os << value.Value<VertexAccessor>();
+    case TypedValue::Type::Edge:
+      return os << value.Value<EdgeAccessor>();
+    case TypedValue::Type::Path:
+      return os << value.Value<Path>();
   }
   permanent_fail("Unsupported PropertyValue::Type");
 }
@@ -176,18 +226,30 @@ TypedValue& TypedValue::operator=(const TypedValue& other) {
       case TypedValue::Type::Bool:
         this->bool_v = other.bool_v;
         return *this;
-      case TypedValue::Type::String:
-        new (&string_v) std::string(other.string_v);
-        return *this;
       case TypedValue::Type::Int:
         this->int_v = other.int_v;
         return *this;
       case TypedValue::Type::Double:
         this->double_v = other.double_v;
         return *this;
+      case TypedValue::Type::String:
+        new (&string_v) std::string(other.string_v);
+        return *this;
       case TypedValue::Type::List:
         new (&list_v) std::vector<TypedValue>(other.list_v);
         return *this;
+      case TypedValue::Type::Map:
+        new (&map_v) std::map<std::string, TypedValue>(other.map_v);
+        return *this;
+      case TypedValue::Type::Vertex:
+        new (&vertex_v) VertexAccessor(other.vertex_v);
+        return *this;
+      case TypedValue::Type::Edge:
+        new (&edge_v) EdgeAccessor(other.edge_v);
+        return *this;
+      case TypedValue::Type::Path:
+        new (&path_v) Path(other.path_v);
+        return *this;
     }
   }
   permanent_fail("Unsupported TypedValue::Type");
@@ -216,6 +278,19 @@ TypedValue::~TypedValue() {
       using namespace std;
       list_v.~vector<TypedValue>();
       return;
+    case Type::Map:
+      using namespace std;
+      map_v.~map<std::string, TypedValue>();
+      return;
+    case Type::Vertex:
+      vertex_v.~VertexAccessor();
+      return;
+    case Type::Edge:
+      edge_v.~EdgeAccessor();
+      return;
+    case Type::Path:
+      path_v.~Path();
+      return;
   }
   permanent_fail("Unsupported TypedValue::Type");
 }
diff --git a/src/query/backend/cpp/typed_value.hpp b/src/query/backend/cpp/typed_value.hpp
index 77c0dc6f1..84de55e30 100644
--- a/src/query/backend/cpp/typed_value.hpp
+++ b/src/query/backend/cpp/typed_value.hpp
@@ -4,11 +4,17 @@
 #include <memory>
 #include <string>
 #include <vector>
+#include <map>
 
 #include "utils/exceptions/stacktrace_exception.hpp"
 #include "utils/total_ordering.hpp"
 #include "utils/underlying_cast.hpp"
 #include "storage/property_value.hpp"
+#include "storage/edge_accessor.hpp"
+#include "storage/vertex_accessor.hpp"
+#include "traversal/path.hpp"
+
+typedef traversal_template::Path<VertexAccessor, EdgeAccessor> Path;
 
 /**
  * Encapsulation of a value and it's type encapsulated in a class that has no
@@ -24,7 +30,18 @@ class TypedValue : public TotalOrdering<TypedValue, TypedValue, TypedValue> {
 
  public:
   /** A value type. Each type corresponds to exactly one C++ type */
-  enum class Type : unsigned { Null, String, Bool, Int, Double, List };
+  enum class Type : unsigned {
+    Null,
+    Bool,
+    Int,
+    Double,
+    String,
+    List,
+    Map,
+    Vertex,
+    Edge,
+    Path
+  };
 
   // single static reference to Null, used whenever Null should be returned
   static const TypedValue Null;
@@ -37,7 +54,7 @@ class TypedValue : public TotalOrdering<TypedValue, TypedValue, TypedValue> {
   // conversion function to PropertyValue
   operator PropertyValue() const;
 
-  /// constructors for non-primitive types (shared pointers)
+  /// constructors for non-primitive types
   TypedValue(const std::string& value) : type_(Type::String) {
     new (&string_v) std::string(value);
   }
@@ -47,6 +64,17 @@ class TypedValue : public TotalOrdering<TypedValue, TypedValue, TypedValue> {
   TypedValue(const std::vector<TypedValue>& value) : type_(Type::List) {
     new (&list_v) std::vector<TypedValue>(value);
   }
+  TypedValue(const std::map<std::string, TypedValue>& value)
+      : type_(Type::Map) {
+    new (&map_v) std::map<std::string, TypedValue>(value);
+  }
+  TypedValue(const VertexAccessor& vertex) : type_(Type::Vertex) {
+    new (&vertex_v) VertexAccessor(vertex);
+  }
+  TypedValue(const EdgeAccessor& edge) : type_(Type::Edge) {
+    new (&edge_v) EdgeAccessor(edge);
+  }
+  TypedValue(const Path& path) : type_(Type::Path) { new (&path_v) Path(path); }
   TypedValue(const PropertyValue& value);
 
   // assignment ops
@@ -82,7 +110,12 @@ class TypedValue : public TotalOrdering<TypedValue, TypedValue, TypedValue> {
     // because of data locality.
     std::string string_v;
     std::vector<TypedValue> list_v;
-    // Node, Edge, Path, Map missing.
+    // clang doesn't allow unordered_map to have incomplete type as value so we
+    // we use map.
+    std::map<std::string, TypedValue> map_v;
+    VertexAccessor vertex_v;
+    EdgeAccessor edge_v;
+    Path path_v;
   };
 
   /**