78 votes

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

Je suis en train de me débarrasser de mon tslint erreur Type declaration of 'any' loses type-safety. mais j'ai du mal à comprendre ce que le type correct serait pour l'Événement.

Je travaille par le biais de la Lynda "la Construction et le Déploiement d'un Full-Stack Réagir Application" tout en essayant de le convertir en texte dactylographié.

Voici les lignes qui sont à l'origine du problème:

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

J'ai essayé de déclarer l'événement que peu de types différents, comme React.MouseEvent<HTMLElement>, ainsi que quelques autres types de HTMLElement, sans le moindre succès en tant que cible.l'indice n'est pas une propriété sur n'importe quel type, je peux venir avec. Je peux voir dans l'inspecteur que l'currentTarget est Konva.Le texte et l'indice est fixée à l' 0 mais pas sûr que ça m'aide car je ne peux pas définir le type d' Konva.Text, ce qui serait logique pour moi, mais cela ne fonctionne pas non plus.

React Konva Event target Index

Voici mon Réagir composante fonctionnelle:

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 package.json dépendances:

  "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 que l'index est ajouté par l'Konva Couche de la classe, mais je suis assez nouveau à l'ensemble de réagir écosystème encore en train d'envelopper mon cerveau autour de ça.

Mise à JOUR:

J'ai été en mesure d'utiliser la déclaration de la fusion de suggestion par Tyler Sebastion de définir l'index sur la cible, ce qui réduit au silence tslint. Je ne suis pas sûr que c'est la meilleure approche, même si, comme il se sent un peu fragile pour moi.

Ici est le code de l'interface et de la mise à jour de l'événement onclick:

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)
    }}
  />
)

106voto

Tyler Sebastian Points 170

Vous êtes probablement hors de la chance sans hack-y des solutions de contournement

Vous pouvez essayer de

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

Je ne suis pas sûr de la façon stricte à vos linter est - qui pourrait l'arrêter, juste un peu

J'ai joué un peu avec elle pour un peu, et ne pouvait pas le comprendre, mais vous pouvez aussi regarder dans l'écriture de votre propre augmentée définitions: https://www.typescriptlang.org/docs/handbook/declaration-merging.html

edit: merci d'utiliser la mise en œuvre de cette réponse , il est la bonne façon de résoudre ce problème (et aussi upvote lui, pendant que vous y êtes).

21voto

Asimov Points 52

React.MouseEvent fonctionne pour moi:

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

16voto

Justin Levi Winter Points 781

Comme posté dans ma mise à jour ci-dessus, une solution possible serait d'utiliser de la Déclaration de la Fusion, tel que suggéré par @Tyler-sebastion. J'ai été en mesure de définir deux interfaces supplémentaires et ajouter la propriété index sur l' EventTarget de cette façon.

interface KonvaTextEventTarget extends EventTarget {
  index: number
}

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

Je puis déclarer l'événement en tant que KonvaMouseEvent dans mon onclick MouseEventHandler fonction.

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

Je ne suis pas encore à 100% si c'est la meilleure approche, car il se sent un peu Encombrants et trop bavard juste pour avoir passé la tslint erreur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X