Home > Back-end >  How do you let TypeScript know that the state variable and setter function are different types and n
How do you let TypeScript know that the state variable and setter function are different types and n

Time:08-20

I've written a custom hook to rotate a 2d array that returns a state, matrix: string[][], and a function to rotate that matrix, rotateMatrix: () => void. When used in a component, TypeScript wants to refer to both 'matrix' and 'rotateMatrix' as a union type of both string[][] and ()=> void.

Unfortunately, this means that I cannot access the indices of 'matrix' because TypeScript can't be sure it is indeed a string[][], and I can't call 'rotateMatrix' because TypeScript can't be sure it is indeed a function.

How do I inform TypeScript that the state variable and function returned by a custom hook are their own definite types?

Snippet of my code:

type Matrix = (string | undefined) [][];

const testBoard: Matrix = [
  ['y', 'yx', 'y', 'yx', 'y', 'y', 'r', 'r'],
  ['y', 'y', 'y', 'y', 'y', 'y', 'r', 'rx'],
  ['o', 'o', 'o', 'o', 'y', 'yx', 'yx', 'y'],
  ['o', 'ox', 'ox', 'o', 'y', 'y', 'y', 'y'],
  ['g', 'gx', 'b', 'b', 'b', 'b', 't', 't'],
  ['gx', 'g', 'b', 'b', 'b', 'bx', 'tx', 't'],
  ['t', 't', 'b', 'bx', 'b', 'b', 't', 't'],
  ['tx', 't', 'b', 'b', 'bx', 'b', 't', 'tx']
];

function Board() {
  
  const [board, rotateBoard] = useRotation(testBoard);
  const [tiles, setTiles] = useState<TileProps[] | null>(null);

  useEffect(() => {
  
    const tileArr: TileProps[] = [];
    
    for (let y=0; y < board[0].length; y  = 2) {
      for (let x=0; x< board.length; x  = 2) {
        const tile: TileProps = {
          squares: [board[y][x], board[y][x 1], board[y 1][x 1], board[y 1][x]].join('_'),
          row: y,
          column: x,
          gridRow: gridNumbers[y],
          gridColumn: gridNumbers[x]
        };
        tileArr.push(tile);
      }
    }
    setTiles(tileArr);

  }, [board])

  return (
    <>
      { tiles
          ? <BoardFoundation onClick={rotateBoard}>
              {tiles.map((tile: TileProps, index: number) => {
              return <Tile key={index} squares={tile['squares']} row={tile.row} column={tile.column} gridRow={tile.gridRow} gridColumn={tile.gridColumn} />
              })}
            </BoardFoundation>
          : null
      }
    </>
  )
}

function useRotation( matrixNeedingRotation : Matrix ): ((Matrix | (() => void))[]) {

  const [matrix, setMatrix] = useState<Matrix>(matrixNeedingRotation);

  function rotateMatrix(): void {
    const newMatrix = zip(...matrix);
    setMatrix(newMatrix);
  }
 
  return [matrix, rotateMatrix];
}

Thank you very much for your help.

CodePudding user response:

Use a tuple as the return type of the function. It's going to be like the following:

function useRotation( matrixNeedingRotation : Matrix ): [Matrix, (() => void)] {

  const [matrix, setMatrix] = useState<Matrix>(matrixNeedingRotation);

  function rotateMatrix(): void {
    const newMatrix = zip(...matrix);
    setMatrix(newMatrix);
  }

  return [matrix, rotateMatrix];
}
  • Related