web-dev-qa-db-fra.com

Spécification du type d'événement onClick avec TypeScript et React.Konva

J'essaie de me débarrasser de mon erreur tslint Type declaration of 'any' loses type-safety. mais j'ai du mal à trouver le type correct pour l'événement.

Je travaille avec Lynda " Création et déploiement d'une application complète React Application _) " en essayant de la convertir en TypeScript.

Voici les lignes spécifiques à l'origine du problème:

onClick={(event: any) => {
 makeMove(ownMark, event.target.index)
}}

J'ai essayé de déclarer l'événement sous différents types, tels que React.MouseEvent<HTMLElement>, ainsi que quelques autres sous-types sur HTMLElement, sans succès, car le target.index n'est une propriété d'aucun type que je puisse créer. Je peux voir dans l'inspecteur que la cible actuelle est Konva.Text et que l'index est défini sur 0, mais je ne suis pas sûr que cela m'aide, car je ne peux pas définir le type sur Konva.Text, ce qui serait logique. moi, mais ça ne marche pas non plus.

React Konva Event target Index

Voici mon composant fonctionnel complet React:

export const Squares = ({units, coordinates, gameState, win, gameOver, yourTurn, ownMark, move}: SquaresProps) => {
  let squares = coordinates.map( (position: number, index: number) => { 
    let makeMove = move
    let mark = gameState[index] !== 'z' ? gameState[index] : false
    let fill = 'black'

    // when someone wins you want the square to turn green
    if (win && win.includes(index)) {
      fill = 'lightGreen'
    }

    if (gameOver || !yourTurn || mark) {
      makeMove = () => console.log('nope!')
    }

    return (
      <Text
        key={index}
        x={position[0]}
        y={position[1]}
        fontSize={units}
        width={units}
        text={mark}
        fill={fill}
        fontFamily={'Helvetica'}
        aligh={'center'}
        onClick={(event: any) => {
          makeMove(ownMark, event.target.index)
        }}
      />
    )
  })

  return (
    <Layer>
      {squares}
    </Layer>
  )
}

Voici mes dépendances package.json:

  "dependencies": {
    "konva": "^1.6.3",
    "material-ui": "^0.18.4",
    "react": "^15.6.1",
    "react-dom": "^15.6.1",
    "react-konva": "^1.1.3",
    "react-router": "~3.0.0",
    "react-tap-event-plugin": "^2.0.1",
    "styled-components": "^2.1.0"
  },

Je pense l'indice est ajouté par la classe de couches de Konva mais je suis assez nouveau dans l'ensemble de l'écosystème réactif, j'essaie donc encore de m'envelopper dans mon cerveau. tout.

MISE À JOUR:

J'ai pu utiliser la proposition de fusion de déclaration de Tyler Sebastion pour définir l'index sur la cible qui a réduit le silence au silence. Je ne suis pas sûr que ce soit la meilleure approche, car cela me semble un peu fragile.

Voici le code d'interface supplémentaire et l'événement onclick mis à jour:

interface KonvaTextEventTarget extends EventTarget {
  index: number
}

interface KonvaMouseEvent extends React.MouseEvent<HTMLElement> {
  target: KonvaTextEventTarget
}

...

return (
  <Text
    key={index}
    x={position[0]}
    y={position[1]}
    fontSize={units}
    width={units}
    text={mark}
    fill={fill}
    fontFamily={'Helvetica'}
    aligh={'center'}
    onClick={(event: KonvaMouseEvent) => {
      makeMove(ownMark, event.target.index)
    }}
  />
)
36
Justin Levi Winter

Comme indiqué dans ma mise à jour ci-dessus, une solution potentielle serait d'utiliser la fusion de déclaration comme suggéré par @ Tyler-sebastion. J'ai pu définir deux interfaces supplémentaires et ajouter la propriété index sur la variable EventTarget de cette manière.

interface KonvaTextEventTarget extends EventTarget {
  index: number
}

interface KonvaMouseEvent extends React.MouseEvent<HTMLElement> {
  target: KonvaTextEventTarget
}

Je peux ensuite déclarer l'événement comme KonvaMouseEvent dans ma fonction onclick MouseEventHandler.

onClick={(event: KonvaMouseEvent) => {
          makeMove(ownMark, event.target.index)
}}

Je ne suis toujours pas à 100% si c'est la meilleure approche, car on se sent un peu kludgy et trop bavard juste pour aller au-delà de l'erreur tslint.

9
Justin Levi Winter

Vous n'avez probablement pas de chance sans certaines solutions de contournement

Tu pourrais essayer

onClick={(event: React.MouseEvent<HTMLElement>) => {
 makeMove(ownMark, (event.target as any).index)
}}

Je ne sais pas à quel point votre linter est strict - cela pourrait le faire taire un peu

Je me suis un peu amusé avec elle, mais je ne pouvais pas le comprendre, mais vous pouvez aussi envisager de rédiger vos propres définitions augmentées: https://www.typescriptlang.org/docs/handbook/declaration-merging .html

edit: veuillez utiliser l’implémentation dans cette réponse c’est le moyen approprié de résoudre ce problème (et aussi de l’invoquer, alors que vous y êtes).

41
Tyler Sebastian

React.MouseEvent fonctionne pour moi:

private onClick = (e: React.MouseEvent<HTMLInputElement>) => {
  let button = e.target as HTMLInputElement;
}
8
Asimov