Skip to content

Commit 468fa92

Browse files
committed
fix: wrong type information for #await with same id
1 parent 182c6cb commit 468fa92

File tree

4 files changed

+94
-1
lines changed

4 files changed

+94
-1
lines changed

src/parser/converts/block.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,11 @@ export function convertAwaitBlock(
307307
};
308308
}
309309
const idAwaitThenValue = typeCtx.generateUniqueId("AwaitThenValue");
310-
if (node.expression.type === "Identifier") {
310+
if (
311+
node.expression.type === "Identifier" &&
312+
// We cannot use type annotations like `(x: Foo<x>)` if they have the same identifier name.
313+
!hasIdentifierFor(node.expression.name, baseParam.node)
314+
) {
311315
return {
312316
preparationScript: [generateAwaitThenValueType(idAwaitThenValue)],
313317
param: {
@@ -484,3 +488,30 @@ function generateAwaitThenValueType(id: string) {
484488
: never
485489
: T;`;
486490
}
491+
492+
/** Checks whether the given name identifier is exists or not. */
493+
function hasIdentifierFor(name: string, node: ESTree.Pattern): boolean {
494+
if (node.type === "Identifier") {
495+
return node.name === name;
496+
}
497+
if (node.type === "ObjectPattern") {
498+
return node.properties.some((property) =>
499+
property.type === "Property"
500+
? hasIdentifierFor(name, property.value)
501+
: hasIdentifierFor(name, property)
502+
);
503+
}
504+
if (node.type === "ArrayPattern") {
505+
return node.elements.some(
506+
(element) => element && hasIdentifierFor(name, element)
507+
);
508+
}
509+
if (node.type === "RestElement") {
510+
return hasIdentifierFor(name, node.argument);
511+
}
512+
if (node.type === "AssignmentPattern") {
513+
return hasIdentifierFor(name, node.left);
514+
}
515+
516+
return false;
517+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<script lang="ts">
2+
let a: Promise<{ x: number }>
3+
let b: Promise<{ x: number }>
4+
let c: Promise<{ x: number }>
5+
let d: Promise<number[]>
6+
let e: Promise<number[]>
7+
</script>
8+
9+
{#await a}
10+
<div>await</div>
11+
{:then a}
12+
<div>{a.x}</div>
13+
{/await}
14+
15+
{#await b}
16+
<div>await</div>
17+
{:then { x: b = 42 }}
18+
<div>{b.toExponential()}</div>
19+
{/await}
20+
21+
{#await c}
22+
<div>await</div>
23+
{:then {...c}}
24+
<div>{c.x}</div>
25+
{/await}
26+
27+
{#await d}
28+
<div>await</div>
29+
{:then [d]}
30+
<div>{d.toExponential()}</div>
31+
{/await}
32+
33+
{#await e}
34+
<div>await</div>
35+
{:then [...e]}
36+
<div>{e[0].toExponential()}</div>
37+
{/await}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[]
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/* eslint eslint-comments/require-description: 0, @typescript-eslint/explicit-module-boundary-types: 0 */
2+
import type { Linter } from "eslint";
3+
import { generateParserOptions } from "../../../src/parser/test-utils";
4+
import { rules } from "@typescript-eslint/eslint-plugin";
5+
export function setupLinter(linter: Linter) {
6+
linter.defineRule(
7+
"@typescript-eslint/no-unsafe-member-access",
8+
rules["no-unsafe-member-access"] as never
9+
);
10+
}
11+
12+
export function getConfig() {
13+
return {
14+
parser: "svelte-eslint-parser",
15+
parserOptions: generateParserOptions(),
16+
rules: {
17+
"@typescript-eslint/no-unsafe-member-access": "error",
18+
},
19+
env: {
20+
browser: true,
21+
es2021: true,
22+
},
23+
};
24+
}

0 commit comments

Comments
 (0)