質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
React Native

React Nativeは、ネイティブモバイルアプリ(iOS/Android)を作成できるJavaScriptフレームワークです。Reactと同じ設計のため、宣言的なコンポーネントでリッチなUIを開発することが可能です。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

Q&A

2回答

471閲覧

addEventListenerのlistenerに渡す関数の引数の型が一致しないためエラーになる

Praline

総合スコア46

React Native

React Nativeは、ネイティブモバイルアプリ(iOS/Android)を作成できるJavaScriptフレームワークです。Reactと同じ設計のため、宣言的なコンポーネントでリッチなUIを開発することが可能です。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

0グッド

0クリップ

投稿2023/12/31 14:27

実現したいこと

Typescript初学者です。
ドラッグで動かすことができるコンポーネントを実装するために、
EventListenerを管理したいと思っております。

発生している問題・分からないこと

マウスを動かすイベント、マウスを離したときの処理をそれぞれ関数にし、
マウスを押したときにイベントリスナに追加したいのですが、
引数の型が違うためにエラーが発生します。

エラーメッセージ

error

1この呼び出しに一致するオーバーロードはありません。 2 2 中 1 のオーバーロード, '(type: "mousemove", listener: (this: Document, ev: MouseEvent) => any, options?: boolean | AddEventListenerOptions | undefined): void' により、次のエラーが発生しました。 3 型 '(e: MouseEvent) => void' の引数を型 '(this: Document, ev: MouseEvent) => any' のパラメーターに割り当てることはできません。 4 パラメーター 'e' および 'ev' は型に互換性がありません。 5 型 'MouseEvent' には 型 'MouseEvent<Element, MouseEvent>' からの次のプロパティがありません: nativeEvent, isDefaultPrevented, isPropagationStopped, persist 6 2 中 2 のオーバーロード, '(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions | undefined): void' により、次のエラーが発生しました。 7 型 '(e: MouseEvent) => void' の引数を型 'EventListenerOrEventListenerObject' のパラメーターに割り当てることはできません。 8 型 '(e: MouseEvent) => void' を型 'EventListener' に割り当てることはできません。 9 パラメーター 'e' および 'evt' は型に互換性がありません。 10 型 'Event' には 型 'MouseEvent<Element, MouseEvent>' からの次のプロパティがありません: altKey, button, buttons, clientX、18 など。

該当のソースコード

Typescript

1import React, { MouseEvent } from 'react'; 2 3const MouseEventItem: React.FC = () => { 4 5 const handleMouseDown = ( e: MouseEvent ) => { 6 document.addEventListener('mousemove', handleMouseMove); 7 document.addEventListener('mouseup', handleMouseUp); 8 } 9 10 const handleMouseMove = (e: MouseEvent ) => { 11 //処理 12 } 13 14 const handleMouseUp = () => { 15 document.removeEventListener('mousemove', handleMouseMove); 16 document.removeEventListener('mouseup', handleMouseUp); 17 } 18 19 return ( 20 <div onMouseDown={handleMouseDown} /> 21 ) 22} 23 24export default function MouserEventComponent() { 25 return ( 26 <MouseEventItem /> 27 ); 28}

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

他の方が書かれているサンプルコードなどを参考にしているのですが、その書き方では特に型を指定する事がありませんでした。

また、同様のエラーが発生する方の忘備録などを参考にしたのですが、

  • リスト"strictFunctionTypes": falseはTypescriptで型定義を厳密にしたいため、今回は採用したくない
  • リストdocument.addEventListener('mousemove', handleMouseMove as any)という指定も同様の理由で不採用
  • リスト 引数の定義にevent: HTMLElementEvent<HTMLInputElement>としたところ、'HTMLElementEvent' という名前は見つかりません。とエラーが発生します。

と、型指定に影響がありそうな箇所は色々試したのですが、どの手段でも解決できず手に負えない次第です。

補足

特になし

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

そのコードに於いて、document.addEventListener の第二引数に指定したハンドラで期待されているのは、React.MouseEventではなく、ネイティブのMouseEventです。

質問のコードでは、冒頭で

import React, { MouseEvent } from 'react';

としているので、10行目の

const handleMouseMove = (e: MouseEvent ) => {

のMouseEventは、React.MouseEvent になってしまっています。

したがって、下記のように、handleMouseMove には ネイティブの MouseEvent を指定するようにすれば解決します。

ts

1import React, { MouseEvent } from 'react'; // React.MouseEvent をインポートしている。 2 3const MouseEventItem: React.FC = () => { 4 const handleMouseDown = (e: MouseEvent) => { // ここのMouseEventは「React.MouseEvent」を意味する。 5 document.addEventListener('mousemove', handleMouseMove); 6 document.addEventListener('mouseup', handleMouseUp); 7 } 8 9 const handleMouseMove = ( e: globalThis.MouseEvent) => { // 修正:ネイティブのMouseEventを指定 10 //処理 11 } 12以下略

または、 importから { MouseEvent } from 'react' を削除し、
handleMouseDown には、React.MouseEvent を指定するようにします。

ts

1import React from 'react'; // { MouseEvent } を削除 2 3const MouseEventItem: React.FC = () => { 4 const handleMouseDown = (e: React.MouseEvent ) => { // 修正 5 document.addEventListener('mousemove', handleMouseMove); 6 document.addEventListener('mouseup', handleMouseUp); 7 } 8 9 const handleMouseMove = ( e: MouseEvent) => { // ここはネイティブのMouseEventを指定したことになる 10 //処理 11 } 12 13以下略

投稿2023/12/31 23:44

編集2024/01/01 00:22
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Praline

2024/01/01 01:34

ご回答ありがとうございます。 MouseEventに種類があるという発想がありませんでした… ご指摘の内容でエラーが解消しました。 後学のために質問となるのですが、いずれの例の場合も渡すMouseEventが関数で異なりますが、 (handleMouseDownではReactのMouseEvent、handleMouseMoveはDOMのマウスイベント) これはTypescriptでは一般的な作法でしょうか。
退会済みユーザー

退会済みユーザー

2024/01/03 09:08 編集

> (handleMouseDownではReactのMouseEvent、handleMouseMoveはDOMのマウスイベント) 質問のコードの場合、handleMouseDown は JSXの中で呼び出しているから、引数の型はReactのイベントになるのに対し、 handleMouseMove の呼び出しは、document.addEventListener で登録しているから、(呼び出されたときの)引数の型はネイティブのイベントになる、というだけだと思います。 多分、クリックしたときにイベントを登録する処理と、マウスを移動・マウスボタンを離した際のイベントの処理や命名がごっちゃになっているのが、混乱の原因ではないでしょうか。 下記では、わかりやすく handleMouseDown を registerMouseEvents に改名したコードになります。 (ただ、質問のコードは省略されており全体像がわからず、処理については、MouseUpをJSXで指定していない理由など含めて、完全に推測であり動作保証できません。これ以上のアドバイスは、全部のコードを見ないことにはできないでしょう) ``` import React, { MouseEvent } from 'react'; const MouseEventItem: React.FC = () => { const registerMouseEvents = ( e: MouseEvent ) => { // JSXの onMouseDown プロパティで指定されているハンドラ。 document.addEventListener('mousemove', handleMouseMove); document.addEventListener('mouseup', handleMouseUp); } const handleMouseMove = (e: globalThis.MouseEvent ) => { // document.addEventListenerで指定されているハンドラ。 //処理 } const handleMouseUp = () => { // もし引数を入れるなら、e: globalThis.MouseEvent document.removeEventListener('mousemove', handleMouseMove); document.removeEventListener('mouseup', handleMouseUp); } return ( <div onMouseDown={registerMouseEvents} /> ) } ```
guest

0

実は、MouseEvent型には、DOMネイティブなものと、React用のものと2種類があります。React用のものをネイティブのdocument.addEventListenerから呼ばれるハンドラの引数とすることはできません。

両方使いたい場合、reactからMouseEventをインポートせず、DOM用のはそのままMouseEventと、React用のものはReact.MouseEventのように書き分けてください。

投稿2023/12/31 23:04

編集2023/12/31 23:49
maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2023/12/31 23:06

あと、関数コンポーネント内の関数は、コンポーネントが再描画されるたびに再作成されるので、removeEventListenerは正しく動きません。 documentへのイベント登録はさせっぱなしにしたうえで、押されたかの状態フラグをrefに入れて、押されているときだけ動かす、という形で組んだほうがいいです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問