Finding valid path on 2D Grid
At several places in your code the explicit type annotation is not
needed, for example

var from: Int = start.column
var to: Int = move.end.column + 1


can be simplified because the compiler infers the type automatically:

var from = start.column
var to = move.end.column + 1


Checking for empty fields along the move can be simplified if you iterate
over a stride(), that allows stepping both in increasing and decreasing
order. In func isValidHorizontal() that would be

let direction = (move.end.column - start.column).signum()
for column in stride(from: start.column + direction,
                     to: move.end.column,
                     by: direction) {
    if board.tileType(at: GameBoardPosition(row: start.row, column: column)) != .empty {
        return false
    }
}
return true


This can further be shortened to

return stride(from: start.column + direction,
                to: move.end.column,
                by: direction).allSatisfy {
    board.tileType(at: GameBoardPosition(row: start.row, column: $0)) == .empty
}


using the allSatisfy(_:)
method introduced in Swift 4.2.

This approach can be applied to the other methods as well.

In func isValidDiagonal() you can check if a destination position can
be reached before walking along the diagonal. For example, if the start position
is (0, 0) then an end position (x, y) can be reached only if x == y.

Further remarks:

You have defined the start property in GameMove as optional 
(in contrast to the end property). Does it really make sense to specify
only the end position in a move? If not then make that property non-optional,
that would also make several guard statements like

guard let start = move.start else { return false }


obsolete.