[英]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-call
和no-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.