Add mechanism for extending data type enums
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
index d988430..a3b8f84 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
@@ -1082,6 +1082,9 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override public T visitTraversalMethod_asNumber_traversalGremlinTypes(final GremlinParser.TraversalMethod_asNumber_traversalGremlinTypesContext ctx) { notImplemented(ctx); return null; }/**
+	 * {@inheritDoc}
+	 */
 	@Override public T visitTraversalScope(final GremlinParser.TraversalScopeContext ctx) { notImplemented(ctx); return null; }
 	/**
 	 * {@inheritDoc}
@@ -1126,6 +1129,10 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override public T visitTraversalGremlinTypes(final GremlinParser.TraversalGremlinTypesContext ctx) { notImplemented(ctx); return null; }
+	/**
+	 * {@inheritDoc}
+	 */
 	@Override public T visitTraversalPredicate(final GremlinParser.TraversalPredicateContext ctx) { notImplemented(ctx); return null; }
 	/**
 	 * {@inheritDoc}
@@ -1158,6 +1165,14 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override public T visitTraversalPredicate_typeOf(final GremlinParser.TraversalPredicate_typeOfContext ctx) { notImplemented(ctx); return null; }
+//	/**
+//	 * {@inheritDoc}
+//	 */
+//	@Override public T visitTraversalPredicate_nof(final GremlinParser.TraversalPredicate_nofContext ctx) { notImplemented(ctx); return null; }
+	/**
+	 * {@inheritDoc}
+	 */
 	@Override public T visitTraversalPredicate_lt(final GremlinParser.TraversalPredicate_ltContext ctx) { notImplemented(ctx); return null; }
 	/**
 	 * {@inheritDoc}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
index eb0b9dc..d9a909b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
@@ -607,6 +607,11 @@
     }
 
     @Override
+    public Object visitTraversalGremlinTypes(final GremlinParser.TraversalGremlinTypesContext ctx) {
+        return antlr.traversalGremlinTypesVisitor.visitGremlinDataType(ctx);
+    }
+
+    @Override
     public Object visitTraversalStrategy(final GremlinParser.TraversalStrategyContext ctx) {
         return antlr.traversalStrategyVisitor.visitTraversalStrategy(ctx);
     }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinAntlrToJava.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinAntlrToJava.java
index ab6dbcc..f7f270e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinAntlrToJava.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinAntlrToJava.java
@@ -29,6 +29,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.GremlinDataType;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
 
@@ -95,6 +96,11 @@
     final TraversalStrategyVisitor traversalStrategyVisitor;
 
     /**
+     * Parses {@link GremlinDataType} instances.
+     */
+    final TraversalGremlinTypesVisitor traversalGremlinTypesVisitor;
+
+    /**
      * Parses {@link P} instances.
      */
     final TraversalPredicateVisitor traversalPredicateVisitor;
@@ -191,6 +197,7 @@
         this.txVisitor = new TraversalSourceTxVisitor(g, this);
         this.traversalPredicateVisitor = new TraversalPredicateVisitor(this);
         this.traversalStrategyVisitor = new TraversalStrategyVisitor(this);
+        this.traversalGremlinTypesVisitor = new TraversalGremlinTypesVisitor(this);
         this.genericVisitor = new GenericLiteralVisitor(this);
         this.argumentVisitor = new ArgumentVisitor(variableResolver, this);
     }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalGremlinTypesVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalGremlinTypesVisitor.java
new file mode 100644
index 0000000..5489028
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalGremlinTypesVisitor.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.language.grammar;
+
+import org.apache.tinkerpop.gremlin.structure.GremlinDataType;
+
+import java.util.Optional;
+
+public class TraversalGremlinTypesVisitor {
+    protected final GremlinAntlrToJava antlr;
+
+    public TraversalGremlinTypesVisitor(final GremlinAntlrToJava antlrToJava) {
+        this.antlr = antlrToJava;
+    }
+
+    public GremlinDataType visitGremlinDataType(final GremlinParser.TraversalGremlinTypesContext ctx) {
+        return tryToConstructGremlinDataType(ctx.getText());
+    }
+
+    /**
+     * Try to instantiate by checking registered {@link GremlinDataType} implementations that are
+     * registered globally. Only strategies that are registered globally can be constructed in this way.
+     */
+    private static GremlinDataType tryToConstructGremlinDataType(final String typeName) {
+        System.out.println(typeName);
+
+        // try to grab the class from registered sources
+        final Optional<GremlinDataType> opt = GremlinDataType.GlobalTypeCache.getRegisteredType(typeName);
+
+        System.out.println(opt);
+
+        if (opt.isEmpty())
+            throw new IllegalStateException("GremlinDataType not recognized - " + typeName);
+
+        return opt.get();
+
+    }
+
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
index 058dea0..1e2546e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
@@ -2128,6 +2128,15 @@
                 TraversalEnumParser.parseTraversalNFromContext(ctx.traversalN()));
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public GraphTraversal visitTraversalMethod_asNumber_traversalGremlinTypes(final GremlinParser.TraversalMethod_asNumber_traversalGremlinTypesContext ctx) {
+        return graphTraversal.asNumber(
+                antlr.traversalGremlinTypesVisitor.visitGremlinDataType(ctx.traversalGremlinTypes()));
+    }
+
     public GraphTraversal[] getNestedTraversalList(final GremlinParser.NestedTraversalListContext ctx) {
         return ctx.nestedTraversalExpr().nestedTraversal()
                 .stream()
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalPredicateVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalPredicateVisitor.java
index ca481c8..849c68b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalPredicateVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalPredicateVisitor.java
@@ -23,8 +23,6 @@
 import org.apache.tinkerpop.gremlin.process.traversal.TextP;
 
 import java.util.Collection;
-import java.util.List;
-import java.util.Set;
 
 public class TraversalPredicateVisitor extends DefaultGremlinBaseVisitor<P> {
 
@@ -83,6 +81,14 @@
      * {@inheritDoc}
      */
     @Override
+    public P visitTraversalPredicate_typeOf(final GremlinParser.TraversalPredicate_typeOfContext ctx) {
+        return P.typeOf(getSingleGenericLiteralArgument(ctx));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     public P visitTraversalPredicate_lt(final GremlinParser.TraversalPredicate_ltContext ctx) {
         return P.lt(getSingleGenericLiteralArgument(ctx));
     }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/PythonTranslateVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/PythonTranslateVisitor.java
index 971e618..b38b925 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/PythonTranslateVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/PythonTranslateVisitor.java
@@ -111,7 +111,7 @@
     public Void visitClassType(final GremlinParser.ClassTypeContext ctx) {
         final Optional<? extends Class<? extends TraversalStrategy>> strategy = TraversalStrategies.GlobalCache.getRegisteredStrategyClass(ctx.getText());
         final String fqcn = strategy.map(Class::getName).orElse(ctx.getText());
-        sb.append("GremlinType('").append(fqcn).append("')");
+        sb.append("GremlinDataType('").append(fqcn).append("')");
         return null;
     }
 
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java
index 917a138..718473d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java
@@ -146,6 +146,15 @@
     }
 
     /**
+     * Determines if values are of a type.
+     *
+     * @since 3.8.0-incubating
+     */
+    public static <V> P<V> typeOf(final V value) {
+        return new P(Type.typeOf, value);
+    }
+
+    /**
      * Determines if a value is less than another.
      *
      * @since 3.0.0-incubating
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Type.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Type.java
new file mode 100644
index 0000000..f1080f0
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Type.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal;
+
+import org.apache.tinkerpop.gremlin.structure.GremlinDataType;
+
+import java.util.Optional;
+
+/**
+ * {@code Type} is a {@code BiPredicate} that determines whether the first argument is a type of the second argument.
+ *
+ */
+public enum Type implements PBiPredicate<Object, Object> {
+
+    /**
+     * Evaluates if the first object is equal to the second per Gremlin Comparison semantics.
+     *
+     * @since 3.8.0
+     */
+    typeOf {
+        @Override
+        public boolean test(final Object first, final Object second) {
+            Class<?> secondClass;
+            if (second instanceof GremlinDataType) {
+                secondClass = ((GremlinDataType) second).getType();
+            } else if (second instanceof String) {
+                try {
+                    // for java class names
+                    secondClass = Class.forName((String) second);
+                } catch (ClassNotFoundException e) {
+                    // for string name of type token we can use the cache
+                    final Optional<GremlinDataType> opt = GremlinDataType.GlobalTypeCache.getRegisteredType((String) second);
+                    if (opt.isEmpty())
+                        return false;
+                    else
+                        secondClass = opt.get().getType();
+                }
+            } else if (second instanceof Class) {
+                secondClass = (Class<?>) second;
+            } else {
+                return false;
+            }
+
+            return (secondClass).isAssignableFrom(first.getClass());
+        }
+
+    },
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
index 2d70e4e..e479b4b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
@@ -195,16 +195,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMetrics;
-import org.apache.tinkerpop.gremlin.structure.Column;
-import org.apache.tinkerpop.gremlin.structure.Direction;
-import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Element;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.Property;
-import org.apache.tinkerpop.gremlin.structure.PropertyType;
-import org.apache.tinkerpop.gremlin.structure.T;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.structure.*;
 import org.apache.tinkerpop.gremlin.util.function.ConstantSupplier;
 
 import java.time.OffsetDateTime;
@@ -1954,6 +1945,16 @@
         return this.asAdmin().addStep(new AsNumberStep<>(this.asAdmin(), numberToken));
     }
 
+    public default GraphTraversal<S, Number> asNumber(final GremlinDataType numberToken) {
+        this.asAdmin().getBytecode().addStep(Symbols.asNumber, numberToken);
+        return this.asAdmin().addStep(new AsNumberStep<>(this.asAdmin(), numberToken));
+    }
+
+    public default GraphTraversal<S, Number> asNumber(final Class numberToken) {
+        this.asAdmin().getBytecode().addStep(Symbols.asNumber, numberToken);
+        return this.asAdmin().addStep(new AsNumberStep<>(this.asAdmin(), numberToken));
+    }
+
     /**
      * Calculates the difference between the list traverser and list argument.
      *
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStep.java
index 29ea000..92bacc9 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStep.java
@@ -23,6 +23,8 @@
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.structure.GType;
+import org.apache.tinkerpop.gremlin.structure.GremlinDataType;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 import org.apache.tinkerpop.gremlin.util.NumberHelper;
 
@@ -35,6 +37,8 @@
 public class AsNumberStep<S> extends ScalarMapStep<S, Number> {
 
     private N numberToken;
+    private GremlinDataType gDT;
+    private Class<?> clazz;
 
     public AsNumberStep(final Traversal.Admin traversal) {
         super(traversal);
@@ -46,16 +50,30 @@
         this.numberToken = numberToken;
     }
 
+    public AsNumberStep(final Traversal.Admin traversal, final GremlinDataType numberToken) {
+        super(traversal);
+        this.gDT = numberToken;
+    }
+
+    public AsNumberStep(final Traversal.Admin traversal, final Class<?> numberToken) {
+        super(traversal);
+        this.gDT = GType.valueOf(numberToken.getSimpleName().toUpperCase());
+    }
+
     @Override
     protected Number map(final Traverser.Admin<S> traverser) {
         final Object object = traverser.get();
         if (object instanceof String) {
             String numberText = (String) object;
             Number number = parseNumber(numberText);
-            return numberToken == null ? number : castNumber(number, numberToken);
+            return numberToken == null ? (gDT == null ? number : castNumber(number, gDT))
+                    : castNumber(number, numberToken);
+//            return numberToken == null ? number : castNumber(number, numberToken);
         } else if (object instanceof Number) {
             Number number = (Number) object;
-            return numberToken == null ? number : castNumber(number, numberToken);
+            return numberToken == null ? (gDT == null ? number : castNumber(number, gDT))
+                    : castNumber(number, numberToken);
+//            return numberToken == null ? number : castNumber(number, numberToken);
         }
         throw new IllegalArgumentException(String.format("Can't parse type %s as number.", object == null ? "null" : object.getClass().getSimpleName()));
     }
@@ -100,4 +118,8 @@
         return NumberHelper.castTo(number, numberToken);
     }
 
+    private static Number castNumber(final Number number, final GremlinDataType numberToken) {
+        return NumberHelper.castTo(number, numberToken);
+    }
+
 }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/PythonTranslator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/PythonTranslator.java
index 907ef24..ae342b5 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/PythonTranslator.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/PythonTranslator.java
@@ -260,7 +260,7 @@
 
         @Override
         protected Script produceScript(final Class<?> o) {
-            return script.append("GremlinType('" + o.getCanonicalName() + "')");
+            return script.append("GremlinDataType('" + o.getCanonicalName() + "')");
         }
 
         @Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/CType.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/CType.java
new file mode 100644
index 0000000..e18e4a9
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/CType.java
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tinkerpop.gremlin.structure;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.function.Function;
+
+public enum CType implements GremlinDataType{
+    ;
+
+    // Registry for custom type mappings
+    private static final ConcurrentMap<String, CustomTypeInfo> CUSTOM_REGISTRY = new ConcurrentHashMap<>();
+
+    // Instance fields for the enum
+    private final Class<?> javaType;
+
+    CType(Class<?> javaType) {
+        this.javaType = javaType;
+    }
+
+
+    @Override
+    public String getName() {
+        return "";
+    }
+
+    @Override
+    public Class<?> getType() {
+        return null;
+    }
+
+    @Override
+    public GremlinDataType fromName(String name) {
+        return null;
+    }
+
+
+    /**
+     * Register a custom TypeToken enum class
+     */
+    public static <E extends Enum<E> & GremlinDataType> void register(
+            String customTypeName,
+            Class<E> enumClass,
+            Function<String, E> factory) {
+
+        CUSTOM_REGISTRY.put(customTypeName, new CustomTypeInfo(enumClass, factory));
+    }
+
+    /**
+     * Register using reflection (convenience method)
+     */
+    public static <E extends Enum<E> & GremlinDataType> void register(
+            String customTypeName,
+            Class<E> enumClass) {
+
+        register(customTypeName, enumClass, name -> Enum.valueOf(enumClass, name));
+    }
+
+    /**
+     * Create a TypeToken instance from a custom type registration
+     */
+    public static Optional<GremlinDataType> createCustomInstance(String customTypeName, String enumValueName) {
+        CustomTypeInfo info = CUSTOM_REGISTRY.get(customTypeName);
+        if (info == null) {
+            return Optional.empty();
+        }
+
+        try {
+            return Optional.of(info.factory.apply(enumValueName));
+        } catch (Exception e) {
+            return Optional.empty();
+        }
+    }
+
+    /**
+     * Get the custom type name for a TypeToken instance
+     */
+    public static Optional<String> getCustomTypeName(GremlinDataType token) {
+        Class<?> tokenClass = token.getClass();
+        return CUSTOM_REGISTRY.entrySet().stream()
+                .filter(entry -> entry.getValue().enumClass.equals(tokenClass))
+                .map(Map.Entry::getKey)
+                .findFirst();
+    }
+
+    /**
+     * Check if a custom type is registered
+     */
+    public static boolean isCustomTypeRegistered(String customTypeName) {
+        return CUSTOM_REGISTRY.containsKey(customTypeName);
+    }
+
+    /**
+     * Get all registered custom type names
+     */
+    public static Set<String> getRegisteredCustomTypes() {
+        return Collections.unmodifiableSet(CUSTOM_REGISTRY.keySet());
+    }
+
+    /**
+     * Check if a TypeToken instance is a custom type
+     */
+    public static boolean isCustomType(GremlinDataType token) {
+        return getCustomTypeName(token).isPresent();
+    }
+
+    // Internal class to hold registration info
+    private static class CustomTypeInfo {
+        final Class<? extends Enum<? extends GremlinDataType>> enumClass;
+        final Function<String, ? extends GremlinDataType> factory;
+
+        CustomTypeInfo(Class<? extends Enum<? extends GremlinDataType>> enumClass,
+                       Function<String, ? extends GremlinDataType> factory) {
+            this.enumClass = enumClass;
+            this.factory = factory;
+        }
+    }
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/CustomType.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/CustomType.java
new file mode 100644
index 0000000..a47a2fd
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/CustomType.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.structure;
+
+/**
+ * Custom types
+ */
+public enum CustomType implements GremlinDataType {
+    POINT(Point.class);
+
+    private final Class<?> javaType;
+
+    CustomType(Class<?> javaType) {
+        this.javaType = javaType;
+    }
+
+    @Override
+    public String getName() { return this.name(); }
+
+    @Override
+    public Class<?> getType() { return javaType; }
+
+    @Override
+    public GremlinDataType fromName(String name) { return CustomType.valueOf(name.toUpperCase()); }
+
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/GType.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/GType.java
new file mode 100644
index 0000000..1a92fad
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/GType.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.structure;
+
+import org.apache.tinkerpop.gremlin.util.NumberHelper;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.time.OffsetDateTime;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Gremlin types
+ */
+public enum GType implements GremlinDataType {
+    BIG_DECIMAL(BigDecimal.class),
+    BIG_INTEGER(BigInteger.class),
+    BOOLEAN(Boolean.class),
+    BYTE(Byte.class),
+    CHARACTER(Character.class),
+    DATETIME(OffsetDateTime.class),
+    DOUBLE(Double.class),
+    FLOAT(Float.class),
+    INT(int.class),
+    INTEGER(Integer.class),
+    LIST(List.class),
+    LONG(Long.class),
+    MAP(Map.class),
+    NUMBER(Number.class),
+    SET(Set.class),
+    SHORT(Short.class),
+    STRING(String.class),
+    UNKNOWN(null),
+    UUID(UUID.class),
+    VERTEX(Vertex.class),;
+
+    private final Class<?> javaType;
+
+    GType(Class<?> javaType) {
+        this.javaType = javaType;
+    }
+
+    @Override
+    public String getName() { return this.name(); }
+
+    @Override
+    public Class<?> getType() { return javaType; }
+
+    @Override
+    public GremlinDataType fromName(String name) { return GType.valueOf(name.toUpperCase()); }
+
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/GremlinDataType.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/GremlinDataType.java
new file mode 100644
index 0000000..bef28c6
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/GremlinDataType.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.structure;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+
+public interface GremlinDataType {
+
+    String getName();
+    Class<?> getType();
+    GremlinDataType fromName(String name);
+
+    // Optional: provide default categorization methods
+    default boolean isPrimitive() {
+        return getType().isPrimitive();
+    }
+
+    default boolean isNumeric() {
+        Class<?> type = getType();
+        return type == int.class || type == Integer.class ||
+                type == long.class || type == Long.class ||
+                type == double.class || type == Double.class ||
+                type == float.class || type == Float.class ||
+                type == BigDecimal.class || type == BigInteger.class;
+    }
+
+    final class GlobalTypeCache {
+
+        private GlobalTypeCache() {
+            throw new IllegalStateException("Utility class");
+        }
+
+        /**
+         * A register of the simple names for all strategies.
+         */
+        private static final Map<String, GremlinDataType> GLOBAL_TYPE_REGISTRY = new ConcurrentHashMap<>() {};
+
+        static {
+            for (GremlinDataType value : GType.values()) {
+                GLOBAL_TYPE_REGISTRY.put("GType." + value.getName(), value);
+            }
+        }
+
+        /**
+         * Registers all constants of a GremlinDataType class by its name (formatted as {GremlinDataType}.{TYPE}), so
+         * it is available to the grammar when parsing Gremlin.
+         */
+        public static void registerDataType(final Class<? extends Enum<? extends GremlinDataType>> enumClass) {
+            for (Enum<? extends GremlinDataType> constant : enumClass.getEnumConstants()) {
+                GLOBAL_TYPE_REGISTRY.put(enumClass.getSimpleName() + "." + constant.name(), (GremlinDataType) constant);
+            }
+        }
+
+        /**
+         * Unregisters a single GremlinDataType Enum constant by its name (formatted as {GremlinDataType}.{TYPE}).
+         * If the GremlinDataType is not in the registry then the grammar cannot reference it
+         */
+        public static void registerDataType(final String name, final GremlinDataType gdt) {
+            GLOBAL_TYPE_REGISTRY.put(name, gdt);
+        }
+
+        /**
+         * Unregisters all constants of a GremlinDataType class. If the GremlinDataType is not in the registry then the
+         * grammar cannot reference it
+         */
+        public static void unregisterDataType(final Class<? extends Enum<? extends GremlinDataType>> enumClass) {
+            for (Enum<? extends GremlinDataType> constant : enumClass.getEnumConstants()) {
+                GLOBAL_TYPE_REGISTRY.remove(enumClass.getSimpleName() + "." + constant.name());
+            }
+        }
+
+        /**
+         * Unregisters a single GremlinDataType by its name (formatted as {GremlinDataType}.{TYPE}). If the GremlinDataType
+         * is not in the registry then the grammar cannot reference it
+         */
+        public static void unregisterDataType(final String name) {
+            GLOBAL_TYPE_REGISTRY.remove(name);
+        }
+
+        /**
+         * Looks up a Gremlin DataType by its simple name.
+         */
+        public static Optional<GremlinDataType> getRegisteredType(final String typeName) {
+            System.out.println(GLOBAL_TYPE_REGISTRY);
+            if (GLOBAL_TYPE_REGISTRY.containsKey(typeName))
+                return Optional.of(GLOBAL_TYPE_REGISTRY.get(typeName));
+
+            return Optional.empty();
+        }
+
+    }
+
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/NType.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/NType.java
new file mode 100644
index 0000000..71219b7
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/NType.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.structure;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+/**
+ * Number types
+ */
+public enum NType implements GremlinDataType {
+    BYTE(Byte.class),
+    SHORT(Short.class),
+    INT(int.class),
+    INTEGER(Integer.class),
+    LONG(Long.class),
+    FLOAT(Float.class),
+    DOUBLE(Double.class),
+    BIG_INTEGER(BigInteger.class),
+    BIG_DECIMAL(BigDecimal.class),;
+
+    private final Class<?> javaType;
+
+    NType(Class<?> javaType) {
+        this.javaType = javaType;
+    }
+
+    @Override
+    public String getName() { return this.name(); }
+
+    @Override
+    public Class<?> getType() { return javaType; }
+
+    @Override
+    public GremlinDataType fromName(String name) { return NType.valueOf(name.toUpperCase()); }
+
+    static {
+        // register types
+//        for (GremlinDataType value : NType.values()) {
+//            GremlinDataType.GlobalTypeCache.registerDataType("NType." + value.getName(), value);
+//        }
+    }
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Point.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Point.java
new file mode 100644
index 0000000..25d27e2
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Point.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tinkerpop.gremlin.structure;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.function.Function;
+
+public class Point {
+    private Integer x;
+    private Integer y;
+
+    // constructors
+    public Point(final Integer x, final Integer y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    // getters and setters
+    public Integer getX() {
+        return x;
+    }
+
+    public Integer getY() {
+        return y;
+    }
+
+    public void setX(final Integer x) {
+        this.x = x;
+    }
+
+    public void setY(final Integer y) {
+        this.y = y;
+    }
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/DataType.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/DataType.java
index c0738a3..112ca4f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/DataType.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/DataType.java
@@ -73,6 +73,7 @@
     MERGE(0x2E),
     DT(0x2F),
     N(0x30),
+    GREMLINDATATYPE(0X31),
 
     CHAR(0X80),
     DURATION(0X81),
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/TypeSerializerRegistry.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/TypeSerializerRegistry.java
index 62597d1..c535332 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/TypeSerializerRegistry.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/TypeSerializerRegistry.java
@@ -40,14 +40,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.util.OrP;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalExplanation;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMetrics;
-import org.apache.tinkerpop.gremlin.structure.Column;
-import org.apache.tinkerpop.gremlin.structure.Direction;
-import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.Property;
-import org.apache.tinkerpop.gremlin.structure.T;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.structure.*;
 import org.apache.tinkerpop.gremlin.structure.io.IoRegistry;
 import org.apache.tinkerpop.gremlin.structure.io.binary.types.*;
 import org.apache.tinkerpop.gremlin.util.function.Lambda;
@@ -123,6 +116,7 @@
             new RegistryEntry<>(DT.class, EnumSerializer.DTSerializer),
             new RegistryEntry<>(Merge.class, EnumSerializer.MergeSerializer),
             new RegistryEntry<>(N.class, new NSerializer()),
+            new RegistryEntry<>(GremlinDataType.class, new GremlinDataTypeSerializer()),
             new RegistryEntry<>(Operator.class, EnumSerializer.OperatorSerializer),
             new RegistryEntry<>(Order.class, EnumSerializer.OrderSerializer),
             new RegistryEntry<>(Pick.class, EnumSerializer.PickSerializer),
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EnumSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EnumSerializer.java
index 7ee0dd0..fccf268 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EnumSerializer.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EnumSerializer.java
@@ -58,6 +58,8 @@
     public static final EnumSerializer<Pop> PopSerializer = new EnumSerializer<>(DataType.POP, Pop::valueOf);
     public static final EnumSerializer<Scope> ScopeSerializer = new EnumSerializer<>(DataType.SCOPE, Scope::valueOf);
     public static final EnumSerializer<T> TSerializer = new EnumSerializer<>(DataType.T, T::valueOf);
+//    public static final EnumSerializer<GType> GTypeSerializer = new EnumSerializer<>(DataType.GTYPE, GType::valueOf);
+//    public static final EnumSerializer<NType> NTypeSerializer = new EnumSerializer<>(DataType.NTYPE, NType::valueOf);
 
     private final Function<String, E> readFunc;
 
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/GremlinDataTypeSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/GremlinDataTypeSerializer.java
new file mode 100644
index 0000000..c3c645e
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/GremlinDataTypeSerializer.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.structure.io.binary.types;
+
+import org.apache.tinkerpop.gremlin.structure.GType;
+import org.apache.tinkerpop.gremlin.structure.GremlinDataType;
+import org.apache.tinkerpop.gremlin.structure.io.Buffer;
+import org.apache.tinkerpop.gremlin.structure.io.binary.DataType;
+import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader;
+import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class GremlinDataTypeSerializer extends SimpleTypeSerializer<GremlinDataType> {
+    // Registry of all known TypeToken implementations
+    private static final Map<String, TypeTokenFactory> TYPE_FACTORIES = new HashMap<>();
+
+    static {
+        // Register your enum types here
+        registerTypeFactory("GType", GType::valueOf);
+        // Add more as needed
+    }
+
+    public GremlinDataTypeSerializer() {
+        super(DataType.GREMLINDATATYPE);
+    }
+
+    /**
+     * Register a factory for creating TypeToken instances from strings
+     */
+    public static void registerTypeFactory(String typeName, TypeTokenFactory factory) {
+        TYPE_FACTORIES.put(typeName, factory);
+    }
+
+    @Override
+    protected GremlinDataType readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException {
+        // Read the enum class name
+        final String enumClassName = context.read(buffer);
+        // Read the enum value name
+        final String enumValueName = context.read(buffer);
+
+        System.out.println("Reading " + enumClassName + " with value " + enumValueName);
+
+        TypeTokenFactory factory = TYPE_FACTORIES.get(enumClassName);
+        if (factory == null) {
+            throw new IOException("Unknown TypeToken enum class: " + enumClassName);
+        }
+
+        try {
+            return factory.create(enumValueName);
+        } catch (Exception e) {
+            throw new IOException("Failed to create TypeToken for " + enumClassName + "." + enumValueName, e);
+        }
+    }
+
+    @Override
+    protected void writeValue(final GremlinDataType value, final Buffer buffer, final GraphBinaryWriter context) throws IOException {
+        // Write the enum class name (simple name)
+        String enumClassName = value.getClass().getSimpleName();
+        context.write(enumClassName, buffer);
+
+        System.out.println("Writing " + enumClassName + " to " + buffer);
+
+        // Write the enum value name
+        if (value instanceof Enum) {
+            context.write(((Enum<?>) value).name(), buffer);
+        } else {
+            // Fallback for non-enum implementations
+            context.write(value.getType(), buffer);
+        }
+    }
+
+    @FunctionalInterface
+    public interface TypeTokenFactory {
+        GremlinDataType create(String name) throws Exception;
+    }
+
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/NumberHelper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/NumberHelper.java
index 41beeaa..017bd55 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/NumberHelper.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/NumberHelper.java
@@ -19,6 +19,7 @@
 package org.apache.tinkerpop.gremlin.util;
 
 import org.apache.tinkerpop.gremlin.process.traversal.N;
+import org.apache.tinkerpop.gremlin.structure.GremlinDataType;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
@@ -712,6 +713,15 @@
         return performConversion(a, clazz);
     }
 
+    public static Number castTo(final Number a, final GremlinDataType numberToken) {
+        Class<? extends Number> clazz = (Class<? extends Number>) numberToken.getType();
+        return performConversion(a, clazz);
+    }
+
+    public static Number castTo(final Number a, final Class<? extends Number> clazz) {
+        return performConversion(a, clazz);
+    }
+
     /**
      * Core conversion logic.
      * Throws ArithmeticException when conversion would overflow.
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java
index 0a6f6b3..b381719 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java
@@ -702,7 +702,7 @@
                             null,
                             "g.withoutStrategies(ReadOnlyStrategy.class)",
                             "g.withoutStrategies(ReadOnlyStrategy)",  // javascript needs TINKERPOP-3055
-                            "g.without_strategies(*[GremlinType('org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy')])"},
+                            "g.without_strategies(*[GremlinDataType('org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy')])"},
                     {"g.withStrategies(ReservedKeysVerificationStrategy(throwException: true, keys: [\"age\"])).addV(\"person\").property(\"age\", 29).property(\"name\", \"marko\")",
                             "g.withStrategies(ReservedKeysVerificationStrategy(throwException:true, keys:[\"age\"])).addV(\"person\").property(\"age\", 29).property(\"name\", \"marko\")",
                             "g.withStrategies(ReservedKeysVerificationStrategy(throwException:boolean0, keys:list0)).addV(string0).property(string1, number0).property(string2, string3)",
@@ -721,7 +721,7 @@
                             null,
                             "g.withoutStrategies(ReadOnlyStrategy.class, PathRetractionStrategy.class, FilterRankingStrategy.class)",
                             "g.withoutStrategies(ReadOnlyStrategy, PathRetractionStrategy, FilterRankingStrategy)",  // javascript - needs TINKERPOP-3055
-                            "g.without_strategies(*[GremlinType('org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy'), GremlinType('org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy'), GremlinType('org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.FilterRankingStrategy')])"},
+                            "g.without_strategies(*[GremlinDataType('org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy'), GremlinDataType('org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy'), GremlinDataType('org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.FilterRankingStrategy')])"},
                     {"g.inject(0..5)",
                             null,
                             "g.inject(number0..number1)",
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java
index 15855e0..bda483b 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java
@@ -21,6 +21,9 @@
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.util.AndP;
 import org.apache.tinkerpop.gremlin.process.traversal.util.OrP;
+import org.apache.tinkerpop.gremlin.structure.CustomType;
+import org.apache.tinkerpop.gremlin.structure.GType;
+import org.apache.tinkerpop.gremlin.structure.Point;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -55,6 +58,10 @@
         @Parameterized.Parameters(name = "{0}.test({1}) = {2}")
         public static Iterable<Object[]> data() {
             return new ArrayList<>(Arrays.asList(new Object[][]{
+                    {P.typeOf(Number.class), 1, true},
+                    {P.typeOf(GType.NUMBER), 1, true},
+                    {P.typeOf(CustomType.POINT), new Point(1, 2), true},
+                    {P.typeOf(Number.class.getCanonicalName()), 1, true},
                     {P.eq(0), 0, true},
                     {P.eq(0), -0, true},
                     {P.eq(0), +0, true},
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStepTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStepTest.java
index ec98bd0..224a587 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStepTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStepTest.java
@@ -22,6 +22,8 @@
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
+import org.apache.tinkerpop.gremlin.structure.GType;
+import org.apache.tinkerpop.gremlin.structure.GremlinDataType;
 import org.junit.Test;
 
 import java.math.BigDecimal;
@@ -49,6 +51,7 @@
         assertEquals(1L, __.__(1L).asNumber().next());
         assertEquals(3.14f, __.__(3.14).asNumber(N.float_).next());
         assertEquals(3.14, __.__(3.14f).asNumber(N.double_).next());
+        assertEquals(3.14, __.__(3.14f).asNumber(GType.DOUBLE).next());
         assertEquals(1, __.__("1").asNumber(N.int_).next());
         assertEquals(1, __.__("1").asNumber().next());
         assertEquals((byte) 1, __.__("1").asNumber(N.byte_).next());
diff --git a/gremlin-language/src/main/antlr4/Gremlin.g4 b/gremlin-language/src/main/antlr4/Gremlin.g4
index a3544cf..0b6ee39 100644
--- a/gremlin-language/src/main/antlr4/Gremlin.g4
+++ b/gremlin-language/src/main/antlr4/Gremlin.g4
@@ -362,6 +362,7 @@
  traversalMethod_asNumber
      : K_ASNUMBER LPAREN RPAREN #traversalMethod_asNumber_Empty
      | K_ASNUMBER LPAREN traversalN RPAREN #traversalMethod_asNumber_traversalN
+     | K_ASNUMBER LPAREN traversalGremlinTypes RPAREN #traversalMethod_asNumber_traversalGremlinTypes
      ;
 
 traversalMethod_asString
@@ -961,6 +962,11 @@
     ARGUMENT AND TERMINAL RULES
 **********************************************/
 
+traversalGremlinTypes
+    : nakedKey
+    | nakedKey DOT nakedKey
+    ;
+
 traversalStrategy
     : K_NEW? classType (LPAREN (configuration (COMMA configuration)*)? RPAREN)?
     ;
@@ -1095,6 +1101,7 @@
     | traversalPredicate_inside
     | traversalPredicate_outside
     | traversalPredicate_between
+    | traversalPredicate_typeOf
     | traversalPredicate_within
     | traversalPredicate_without
     | traversalPredicate_not
@@ -1150,6 +1157,10 @@
     : (K_P DOT K_NEQ | K_NEQ) LPAREN genericArgument RPAREN
     ;
 
+traversalPredicate_typeOf
+    : (K_P DOT K_TYPEOF | K_TYPEOF) LPAREN genericArgument RPAREN
+    ;
+
 traversalPredicate_lt
     : (K_P DOT K_LT | K_LT) LPAREN genericArgument RPAREN
     ;
@@ -1579,6 +1590,7 @@
     | traversalPick
     | traversalDT
     | traversalN
+    | traversalGremlinTypes
     | genericSetLiteral
     | genericCollectionLiteral
     | genericRangeLiteral
@@ -1677,6 +1689,10 @@
     : Identifier
     ;
 
+//gremlinType
+//    : Identifier
+//    ;
+
 // every Gremlin keyword must be listed here or else these words will not be able to be used as
 // Map/Configuration keys as naked identifiers like [all: 123]. without having that definition
 // here that sort of Map definition will get a syntax error.
@@ -2109,6 +2125,7 @@
 K_NEW: 'new';
 K_NORMSACK: 'normSack';
 K_NULL: 'null';
+K_TYPEOF: 'typeOf';
 K_ONCREATE: 'onCreate';
 K_ONMATCH: 'onMatch';
 K_OPERATOR: 'Operator';
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
index 1ba8c43..a2f5a79 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
@@ -22,11 +22,16 @@
 import ch.qos.logback.classic.Logger;
 import nl.altindag.log.LogCaptor;
 import org.apache.tinkerpop.gremlin.driver.Channelizer;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.server.channel.HttpChannelizer;
+import org.apache.tinkerpop.gremlin.structure.CustomType;
+import org.apache.tinkerpop.gremlin.structure.GType;
 import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.io.Mapper;
+import org.apache.tinkerpop.gremlin.structure.GremlinDataType;
+import org.apache.tinkerpop.gremlin.structure.NType;
+import org.apache.tinkerpop.gremlin.structure.Point;
+import org.apache.tinkerpop.gremlin.structure.io.binary.types.GremlinDataTypeSerializer;
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper;
-import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV2;
 import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3;
 import org.apache.tinkerpop.gremlin.util.ExceptionHelper;
 import org.apache.tinkerpop.gremlin.TestHelper;
@@ -44,7 +49,6 @@
 import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteConnection;
 import org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1;
-import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV2;
 import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3;
 import org.apache.tinkerpop.gremlin.util.ser.Serializers;
 import org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin;
@@ -1978,4 +1982,24 @@
             cluster.close();
         }
     }
+
+    @Test
+    public void test() throws Exception {
+        final Cluster cluster = TestClientFactory.build().serializer(Serializers.GRAPHBINARY_V1).create();
+        try {
+            final Client client = cluster.connect().alias("g");
+            final GraphTraversalSource g = traversal().with(DriverRemoteConnection.using(client));
+            GremlinDataType.GlobalTypeCache.registerDataType(NType.class);
+            GremlinDataTypeSerializer.registerTypeFactory("NType", NType::valueOf);
+            GremlinDataType.GlobalTypeCache.registerDataType(CustomType.class);
+            GremlinDataTypeSerializer.registerTypeFactory("CustomType", CustomType::valueOf);
+            System.out.println(g.inject("1").asNumber(NType.DOUBLE).next());
+            System.out.println(client.submit("g.inject('1').asNumber(NType.DOUBLE)", RequestOptions.build().language("gremlin-lang").create()).all().get());
+            System.out.println(g.inject(1.0,2,3,"hello",false).is(P.typeOf(GType.NUMBER)).fold().next());
+            System.out.println(client.submit("g.inject(1.0,'hello').is(P.typeOf(GType.DOUBLE)).fold()", RequestOptions.build().language("gremlin-lang").create()).all().get());
+            cluster.close();
+        } finally {
+            cluster.close();
+        }
+    }
 }