     return lhs.data + rhs.data
 }
 
-public protocol AQTValue {
+/// A protocol that allows other types to be used as a `Value` replacement
+public protocol ValueProtocol {
+    /// You have to be able to provide a BSON `Value`
     var val: Value { get }
 }
 
-extension Value: AQTValue {
+/// Makes it so that a normal BSON `Value` can be used in statements
+extension Value: ValueProtocol {
+    /// The `Value` in `Value` is `self`
     public var val: Value {
         return self
     }
 }
 
+/// Abstract Query Tree.
+///
+/// Made to be easily readable/usable so that an `AQT` instance can be easily translated to a `Document` as a Query or even possibly `SQL` in the future.
 public indirect enum AQT {
-    public enum AQTType {
-        case string
-        case number
-        case int32
-        case int64
-        case double
-        case null
-        case document
-        case array
-        case binary
-        case objectId
-        case regex
-        case jsCode
-        case jsCodeWithScope
-        case timestamp
-        case dateTime
-        case minKey
-        case maxKey
-    }
-    
+    /// The types we support as raw `Int32` values
+    ///
+    /// The raw values are defined in https://docs.mongodb.com/manual/reference/operator/query/type/#op._S_type
+    public enum AQTType: Int32 {
+        /// Any number. So a `.double`, `.int32` or `.int64`
+        case number = -2
+        
+        /// A double
+        case double = 1
+        
+        /// A string
+        case string = 2
+        
+        /// A `Document` I.E. "ordered" `Dictionary`
+        case document = 3
+        
+        /// A `Document` as Array
+        case array = 4
+        
+        /// Binary data
+        case binary = 5
+        
+        // 6 is the deprecated type `undefined`
+        
+        /// A 12-byte unique `ObjectId`
+        case objectId = 7
+        
+        /// A booelan
+        case boolean = 8
+        
+        /// NSDate represented as UNIX Epoch time
+        case dateTime = 9
+        
+        /// Null
+        case null = 10
+        
+        /// A regex with options
+        case regex = 11
+        
+        // 12 is an unsupported DBPointer
+        
+        /// JavaScript Code
+        case jsCode = 13
+        
+        // 14 is an unsupported `Symbol`
+        
+        /// JavaScript code executed within a scope
+        case jsCodeWithScope = 15
+        
+        /// `Int32`
+        case int32 = 16
+        
+        /// Timestamp as milliseconds since UNIX Epoch Time
+        case timestamp = 17
+        
+        /// `Int64`
+        case int64 = 18
+        
+        /// The min-key
+        case minKey = -1
+        
+        /// The max-key
+        case maxKey = 127
+    }
+    
+    /// Returns a Document that represents this AQT as a Query/Filter
     public var document: Document {
         switch self {
+        case .typeof(let key, let type):
+            if type == .number {
+                let aqt = AQT.or([
+                                  .typeof(key: key, type: .double),
+                                  .typeof(key: key, type: .int32),
+                                  .typeof(key: key, type: .int64)
+                                  ])
+                return aqt.document
+                
+            } else {
+                return [key: ["$type": ~type.rawValue]]
+            }
         case .valEquals(let key, let val):
             return [key: ["$eq": val.val]]
         case .valNotEquals(let key, let val):

            return true
        }
    }
}
        return doc
    }
    
    /// Checks if a `Document` matches the given `Query`
    /// 
    /// - parameter query: The `Query` to match this `Document` against
    ///
    /// - returns: Whether this `Document` matches the `Query`
    public func matches(query: Query) -> Bool {
        let doc = self.filterOperators()
        
        switch query.aqt {
        case .typeof(let key, let type):
            return doc[key].typeNumber == type.rawValue
        case .valEquals(let key, let val):
            return doc[key] == val.val
        case .valNotEquals(let key, let val):
