簡體   English   中英

如何在 React 中使用 EventListener 類型?

[英]How to use the EventListener Type in React?

React 在名為global.d.ts的文件中定義了一些(不是全部)DOM 類型,這會導致問題。 在 React 項目中使用EventListener類型(來自 TypeScript lib dom )時似乎存在沖突,因為大多數其他類型都是由 React 聲明的。

有沒有辦法在 React 項目中使用EventListener類型? 我正在使用 next.js,因此在tsconfig.json中使用exclude來丟棄 global.d.ts 文件以使 SSR 工作可能不是一個好主意?

預期(純 TS):
https://codesandbox.io/s/nice-tdd-xnkov?file=/src/index.ts

window.onload = () => {
  // NO Problem: Listener is correct.

  // Explanation:
  // EventListener is coming from typescript (lib.dom.d.ts)
  // MouseEvent is coming from typescript (lib.dom.d.ts)
  const listener: EventListener = (ev: MouseEvent) => {
    console.log("Click!");
  };
  document.body.addEventListener("click", listener);
};

不適用於 React:
https://codesandbox.io/s/react-dom-type-conflict-1y06r?file=/src/App.tsx

useEffect(() => {
  // Problem: Listener is seemingly incorrect.

  // Explanation:
  // EventListener is coming from typescript (lib.dom.d.ts)
  // MouseEvent is coming from react (global.d.ts)
  const listener: EventListener = (ev: MouseEvent) => {
    console.log("Click!");
  };
  document.body.addEventListener("click", listener);
}, []);

解釋,為什么 React 聲明這些類型(來自global.d.ts ):

不包含 DOM 庫的 React 項目需要這些接口來編譯。 React Native 應用程序使用 React,但沒有可用的 DOM。 JavaScript 運行時僅適用於 ES6/ES2015。 這些定義允許此類項目僅使用--lib ES6進行編譯。

警告:所有這些接口都是空的。 如果您想要各種屬性的類型定義(例如 HTMLInputElement.prototype.value),則需要添加--lib DOM (通過命令行或 tsconfig.json)。

這是因為EventListener類型期望參數 ev 是Event類型而不是MouseEvent (實際上是在 lib.dom.d.ts 中定義而不是 global.d.ts)。

您必須像這樣聲明自己的自定義類型:

 const listener: (ev: MouseEvent) => void = (ev: MouseEvent) => {
   console.log("Click!");
 };

或者

 type MouseEventListener =  (ev: MouseEvent) => void;

 const listener: MouseEventListener = (ev: MouseEvent) => {
   console.log("Click!");
 };

我從你那里分叉出來的工作 CodeSandbox

編輯:

你也可以這樣做:

 const listener: EventListener = (ev: Event) => {
   console.log("Click!");
 };

您可以使用三斜杠指令

我在 React + TypeScript 項目中遇到了類似的問題,當使用 DOM API 時,linter ( eslint-typescript ) 標記了幾次違反no-unsafe-callno-unsafe-member-access規則。 例如, document.getElementById("myId")會導致以下兩個錯誤:

ESLint: any類型值的不安全調用。 (@typescript-eslint/no-unsafe-call)

ESLint: any值上的不安全成員 access.getElementById。 (@typescript-eslint/no-unsafe-member-access)

像 @Bugbeeb 和 @Christoph Bühler 一樣,我認為這是因為來自 React 的空類型聲明以某種方式覆蓋了 TypeScript 的內部“lib.dom.d.ts”類型定義。

為了解決這個問題,我使用了三斜杠指令(參見https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html#-reference-lib- )。 在文件的第一行插入///<reference lib="dom"/> ,如下所示:

///<reference lib="dom"/>

// Your code
document.getElementById("myId")
// ...

有了這一行,TypeScript 明確地包含了內置的 lib 文件,並且應該優先於 React 的類型聲明。

Nb:在我從事的項目中,我只需要在一個文件中執行此操作,這也解決了其他文件中的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM