Whenever I use array.map
on a tuple, Typescript infers it as a generic array. For instance, here are some pieces of a simple 3x3 sudoku game:
const _ = ' ' // a "Blank"
type Blank = typeof _
type Cell = number | Blank
type Three = [Cell, Cell, Cell]
type Board = [Three, Three, Three]
const initialBoard: Board = [
[_, 1, 3],
[3, _, 1],
[1, _, _],
]
// Adds a `2` to the first cell on the first row
function applyMove(board: Board): Board {
// đŸ‘‡errors here
const newBoard: Board = board.map((row: Three, index: number) => {
if (index === 0) return <Three> [2, 1, 3]
return <Three> row
})
return newBoard
}
function applyMoveToRow(row: Three): Three {
// return [2, 1, 3] // This works
const newRow: Three = [
2,
...row.slice(1, 3)
]
return newRow
}
The TS error is:
Type '[Cell, Cell, Cell][]' is missing the following properties from type
'[[Cell, Cell, Cell], [Cell, Cell, Cell], [Cell, Cell, Cell]]': 0, 1, 2 .
here it is in a TS Playground.
Is there any way to tell typescript that, when I'm mapping over a tuple, it's going to return a tuple of the same kind, instead of just an array? I've tried being very explicit, annotating all of my return values, etc, but it's not doing the trick.
There's a discussion on the Typescript github about this: https://github.com/Microsoft/TypeScript/issues/11312
But I haven't been able to get a solution out of it.
If you don't mind tweaking the way you assign initialBoard
you can change your Board
definition to this:
interface Board {
[0]: Three,
[1]: Three,
[2]: Three,
map(mapFunction: (row: Three, index: number, array: Board) => Three): Board;
}
This is how you have to change the way you assign a literal to a Board
:
const initialBoard: Board = <Board><any>[
[_, 1, 3],
[3, _, 1],
[1, _, _],
]