Repository: sveltejs/eslint-plugin-svelte (ts)

Issue:
no-top-level-browser-globals rule is flagging types as top level browser globals
### Before You File a Bug Report Please Confirm You Have Done The Following...

- [x] I have tried restarting my IDE and the issue persists.
- [x] I have updated to the latest version of the packages.

### What version of ESLint are you using?

9.27.0

### What version of `eslint-plugin-svelte` are you using?

3.8.0

### What did you do?

```svelte
<script lang="ts">
  let element: HTMLElement;
  let submitHandler: SubmitEvent = (): void => {};
</script>

<form onsubmit={submitHandler}></form>
<div bind:this={element}></div>
```


### What did you expect to happen?

It shouldn't flag types as top level browser globals, because, from my understanding, the objective of this rule is to prevent calling browser specific APIs (e.g. `localStorage`) while in the server.

### What actually happened?

The new `no-top-level-browser-globals` rule is flagging types as top level browser globals.

### Link to **GitHub Repo** with Minimal Reproducible Example

N.A.

### Additional comments

_No response_

Pull request:
fix(no-top-level-browser-globals): false positives for type annotations
fix #1226

Patch:
diff --git a/.changeset/happy-weeks-argue.md b/.changeset/happy-weeks-argue.md
new file mode 100644
index 0000000..8a798dc
--- /dev/null
+++ b/.changeset/happy-weeks-argue.md
@@ -0,0 +1,5 @@
+---
+"eslint-plugin-svelte": patch
+---
+
+fix(no-top-level-browser-globals): false positives for type annotations
diff --git a/packages/eslint-plugin-svelte/src/rules/no-top-level-browser-globals.ts b/packages/eslint-plugin-svelte/src/rules/no-top-level-browser-globals.ts
index a3a94e6..1a997ec 100644
--- a/packages/eslint-plugin-svelte/src/rules/no-top-level-browser-globals.ts
+++ b/packages/eslint-plugin-svelte/src/rules/no-top-level-browser-globals.ts
@@ -37,6 +37,7 @@ export default createRule('no-top-level-browser-globals', {
 		const maybeGuards: MaybeGuard[] = [];
 
 		const functions: TSESTree.FunctionLike[] = [];
+		const typeAnnotations: (TSESTree.TypeNode | TSESTree.TSTypeAnnotation)[] = [];
 
 		function enterFunction(node: TSESTree.FunctionLike) {
 			if (isTopLevelLocation(node)) {
@@ -44,6 +45,12 @@ export default createRule('no-top-level-browser-globals', {
 			}
 		}
 
+		function enterTypeAnnotation(node: TSESTree.TypeNode | TSESTree.TSTypeAnnotation) {
+			if (!isInTypeAnnotation(node)) {
+				typeAnnotations.push(node);
+			}
+		}
+
 		function enterMetaProperty(node: TSESTree.MetaProperty) {
 			if (node.meta.name !== 'import' || node.property.name !== 'meta') return;
 			for (const ref of referenceTracker.iteratePropertyReferences(node, {
@@ -84,7 +91,7 @@ export default createRule('no-top-level-browser-globals', {
 
 			// Collects references to global variables.
 			for (const ref of iterateBrowserGlobalReferences()) {
-				if (!isTopLevelLocation(ref.node)) continue;
+				if (!isTopLevelLocation(ref.node) || isInTypeAnnotation(ref.node)) continue;
 				const guardChecker = getGuardCheckerFromReference(ref.node);
 				if (guardChecker) {
 					const name = ref.path.join('.');
@@ -113,6 +120,7 @@ export default createRule('no-top-level-browser-globals', {
 
 		return {
 			':function': enterFunction,
+			'*.typeAnnotation': enterTypeAnnotation,
 			MetaProperty: enterMetaProperty,
 			'Program:exit': verifyGlobalReferences
 		};
@@ -145,6 +153,19 @@ export default createRule('no-top-level-browser-globals', {
 			return true;
 		}
 
+		/**
+		 * Checks whether the node is in type annotation.
+		 * @returns `true` if the node is in type annotation.
+		 */
+		function isInTypeAnnotation(node: TSESTree.Node) {
+			for (const typeAnnotation of typeAnnotations) {
+				if (typeAnnotation.range[0] <= node.range[0] && node.range[1] <= typeAnnotation.range[1]) {
+					return true;
+				}
+			}
+			return false;
+		}
+
 		/**
 		 * Iterate over the references of modules that can check the browser environment.
 		 */


Test patch:
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-top-level-browser-globals/valid/ts01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-top-level-browser-globals/valid/ts01-input.svelte
new file mode 100644
index 0000000..93b8f55
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-top-level-browser-globals/valid/ts01-input.svelte
@@ -0,0 +1,3 @@
+<script lang="ts">
+	let element: HTMLElement;
+</script>