Little bit late to this, but here's another implementation which uses OptionSet to make its use a bit more like various other SwiftUI components -
struct Swipe: OptionSet, Equatable {
    
    init(rawValue: Int) {
        self.rawValue = rawValue
    }
    
    let rawValue: Int
    
    fileprivate var swiped: ((DragGesture.Value, Double) -> Bool) = { _, _ in false } // prevents a crash if someone creates a swipe directly using the init
    
    private static let sensitivityFactor: Double = 400 // a fairly arbitrary figure which gives a reasonable response
    
    static var left: Swipe {
        var swipe = Swipe(rawValue: 1 << 0)
        swipe.swiped = { value, sensitivity in
            value.translation.width < 0 && value.predictedEndTranslation.width < sensitivity * sensitivityFactor
        }
        return swipe
    }
    static var right: Swipe {
        var swipe = Swipe(rawValue: 1 << 1)
        swipe.swiped = { value, sensitivity in
            value.translation.width > 0 && value.predictedEndTranslation.width > sensitivity * sensitivityFactor
        }
        return swipe
    }
    static var up: Swipe {
        var swipe = Swipe(rawValue: 1 << 2)
        swipe.swiped = { value, sensitivity in
            value.translation.height < 0 && value.predictedEndTranslation.height < sensitivity * sensitivityFactor
        }
        return swipe
    }
    static var down: Swipe {
        var swipe = Swipe(rawValue: 1 << 3)
        swipe.swiped = { value, sensitivity in
            value.translation.height > 0 && value.predictedEndTranslation.height > sensitivity * sensitivityFactor
        }
        return swipe
    }
    
    static var all: Swipe {
        [.left, .right, .up, .down]
    }
    
    private static var allCases: [Swipe] = [.left, .right, .up, .down]
    
    fileprivate var array: [Swipe] {
        Swipe.allCases.filter { self.contains($0) }
    }
}
extension View {
    
    func swipe(_ swipe: Swipe, sensitivity: Double = 1, action: @escaping (Swipe) -> ()) -> some View {
        
        return gesture(DragGesture(minimumDistance: 30, coordinateSpace: .local)
            .onEnded { value in
                swipe.array.forEach { swipe in
                    if swipe.swiped(value, sensitivity) {
                        action(swipe)
                    }
                }
            }
        )
    }
}
In a SwiftUI view -
HStack {
    // content
}
.swipe([.left, .right]) { swipe in // could also be swipe(.left) or swipe(.all), etc
    doSomething(with: swipe)
}
Obviously the logic for detecting swipes is a bit basic, but that's easy enough to tailor to your requirements.