         }
     }
 
+    #if swift(>=4)
+    /**
+     `Promise<[T]>` => `KeyPath<T, U?>` => `Promise<[U]>`
+
+         firstly {
+             .value([Person(name: "Max"), Person(name: "Roman", age: 26), Person(name: "John", age: 23)])
+         }.compactMapValues(\.age).done {
+             // $0 => [26, 23]
+         }
+     */
+    func compactMapValues<U>(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, _ keyPath: KeyPath<T.Iterator.Element, U?>) -> Promise<[U]> {
+        return map(on: on, flags: flags) { foo -> [U] in
+          #if !swift(>=4.1)
+            return foo.flatMap { $0[keyPath: keyPath] }
+          #else
+            return foo.compactMap { $0[keyPath: keyPath] }
+          #endif
+        }
+    }
+    #endif
+
     /**
      `Promise<[T]>` => `T` -> `Promise<U>` => `Promise<[U]>`
 

        return map(on: on, flags: flags){ try $0.map(transform) }
    }

    /**
     `Promise<[T]>` => `T` -> `[U]` => `Promise<[U]>`


            $0.filter(isIncluded)
        }
    }

    #if swift(>=4)
    /**
     `Promise<[T]>` => `KeyPath<T, Bool>` => `Promise<[T]>`

         firstly {
             .value([Person(name: "Max"), Person(name: "Roman", age: 26, isStudent: false), Person(name: "John", age: 23, isStudent: true)])
         }.filterValues(\.isStudent).done {
             // $0 => [Person(name: "John", age: 23, isStudent: true)]
         }
     */
    func filterValues(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, _ keyPath: KeyPath<T.Iterator.Element, Bool>) -> Promise<[T.Iterator.Element]> {
        return map(on: on, flags: flags) {
            $0.filter { $0[keyPath: keyPath] }
        }
    }
    #endif
}

public extension Thenable where T: Collection {
