Skip to content

Commit 080f9c1

Browse files
authored
Fixed false positive errors in empty optional binding patterns in declaration signatures (#50816)
1 parent 9c5b09c commit 080f9c1

File tree

4 files changed

+204
-1
lines changed

4 files changed

+204
-1
lines changed

src/compiler/checker.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25119,7 +25119,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2511925119
}
2512025120

2512125121
function isInAmbientOrTypeNode(node: Node): boolean {
25122-
return !!(node.flags & NodeFlags.Ambient || findAncestor(node, n => isInterfaceDeclaration(n) || isTypeLiteralNode(n)));
25122+
return !!(node.flags & NodeFlags.Ambient || findAncestor(node, n => isInterfaceDeclaration(n) || isTypeAliasDeclaration(n) || isTypeLiteralNode(n)));
2512325123
}
2512425124

2512525125
// Return the flow cache key for a "dotted name" (i.e. a sequence of identifiers
@@ -40653,6 +40653,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4065340653
}
4065440654
// For a binding pattern, validate the initializer and exit
4065540655
if (isBindingPattern(node.name)) {
40656+
if (isInAmbientOrTypeNode(node)) {
40657+
return;
40658+
}
4065640659
const needCheckInitializer = hasOnlyExpressionInitializer(node) && node.initializer && node.parent.parent.kind !== SyntaxKind.ForInStatement;
4065740660
const needCheckWidenedType = !some(node.name.elements, not(isOmittedExpression));
4065840661
if (needCheckInitializer || needCheckWidenedType) {
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
=== tests/cases/compiler/emptyOptionalBindingPatternInDeclarationSignature.ts ===
2+
// #50791
3+
4+
declare function fn1({}?: { x: string }): void;
5+
>fn1 : Symbol(fn1, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 0, 0))
6+
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 2, 27))
7+
8+
declare function fn2({ x }?: { x: string }): void;
9+
>fn2 : Symbol(fn2, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 2, 47))
10+
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 3, 22))
11+
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 3, 30))
12+
13+
declare function fn3([]?: [ x: string ]): void;
14+
>fn3 : Symbol(fn3, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 3, 50))
15+
16+
declare function fn4([ x ]?: [ x: string ]): void;
17+
>fn4 : Symbol(fn4, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 4, 47))
18+
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 5, 22))
19+
20+
declare class C1 {
21+
>C1 : Symbol(C1, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 5, 50))
22+
23+
method({}?: { x: string }): void
24+
>method : Symbol(C1.method, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 7, 18))
25+
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 8, 17))
26+
27+
static method2({}?: { x: string }): void
28+
>method2 : Symbol(C1.method2, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 8, 36))
29+
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 9, 25))
30+
31+
static field: ({}?: { x: string }) => void
32+
>field : Symbol(C1.field, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 9, 44))
33+
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 11, 25))
34+
35+
static field2: ({}?: { x: string }) => void
36+
>field2 : Symbol(C1.field2, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 11, 46))
37+
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 12, 26))
38+
}
39+
40+
interface I1 {
41+
>I1 : Symbol(I1, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 13, 1))
42+
43+
method({}?: { x: string }): void
44+
>method : Symbol(I1.method, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 15, 14))
45+
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 16, 17))
46+
47+
method2: ({}?: { x: string }) => void
48+
>method2 : Symbol(I1.method2, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 16, 36))
49+
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 17, 20))
50+
}
51+
52+
type T1 = ({}?: { x: string }) => void
53+
>T1 : Symbol(T1, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 18, 1))
54+
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 20, 17))
55+
56+
type T2 = {
57+
>T2 : Symbol(T2, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 20, 38))
58+
59+
method({}?: { x: string }): void
60+
>method : Symbol(method, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 22, 11))
61+
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 23, 17))
62+
63+
method2: ({}?: { x: string }) => void
64+
>method2 : Symbol(method2, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 23, 36))
65+
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 24, 20))
66+
}
67+
68+
declare const val1: ({}?: { x: string }) => void
69+
>val1 : Symbol(val1, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 27, 13))
70+
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 27, 27))
71+
72+
declare const val2: {
73+
>val2 : Symbol(val2, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 29, 13))
74+
75+
method({}?: { x: string }): void
76+
>method : Symbol(method, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 29, 21))
77+
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 30, 17))
78+
79+
method2: ({}?: { x: string }) => void
80+
>method2 : Symbol(method2, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 30, 36))
81+
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 31, 20))
82+
}
83+
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
=== tests/cases/compiler/emptyOptionalBindingPatternInDeclarationSignature.ts ===
2+
// #50791
3+
4+
declare function fn1({}?: { x: string }): void;
5+
>fn1 : ({}?: { x: string;}) => void
6+
>x : string
7+
8+
declare function fn2({ x }?: { x: string }): void;
9+
>fn2 : ({ x }?: { x: string;}) => void
10+
>x : string
11+
>x : string
12+
13+
declare function fn3([]?: [ x: string ]): void;
14+
>fn3 : ([]?: [x: string]) => void
15+
16+
declare function fn4([ x ]?: [ x: string ]): void;
17+
>fn4 : ([x]?: [x: string]) => void
18+
>x : string
19+
20+
declare class C1 {
21+
>C1 : C1
22+
23+
method({}?: { x: string }): void
24+
>method : ({}?: { x: string;}) => void
25+
>x : string
26+
27+
static method2({}?: { x: string }): void
28+
>method2 : ({}?: { x: string;}) => void
29+
>x : string
30+
31+
static field: ({}?: { x: string }) => void
32+
>field : ({}?: { x: string;}) => void
33+
>x : string
34+
35+
static field2: ({}?: { x: string }) => void
36+
>field2 : ({}?: { x: string;}) => void
37+
>x : string
38+
}
39+
40+
interface I1 {
41+
method({}?: { x: string }): void
42+
>method : ({}?: { x: string;}) => void
43+
>x : string
44+
45+
method2: ({}?: { x: string }) => void
46+
>method2 : ({}?: { x: string;}) => void
47+
>x : string
48+
}
49+
50+
type T1 = ({}?: { x: string }) => void
51+
>T1 : ({}?: { x: string;}) => void
52+
>x : string
53+
54+
type T2 = {
55+
>T2 : { method({}?: { x: string;}): void; method2: ({}?: { x: string;}) => void; }
56+
57+
method({}?: { x: string }): void
58+
>method : ({}?: { x: string;}) => void
59+
>x : string
60+
61+
method2: ({}?: { x: string }) => void
62+
>method2 : ({}?: { x: string;}) => void
63+
>x : string
64+
}
65+
66+
declare const val1: ({}?: { x: string }) => void
67+
>val1 : ({}?: { x: string;}) => void
68+
>x : string
69+
70+
declare const val2: {
71+
>val2 : { method({}?: { x: string;}): void; method2: ({}?: { x: string;}) => void; }
72+
73+
method({}?: { x: string }): void
74+
>method : ({}?: { x: string;}) => void
75+
>x : string
76+
77+
method2: ({}?: { x: string }) => void
78+
>method2 : ({}?: { x: string;}) => void
79+
>x : string
80+
}
81+
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// @strict: true
2+
// @noEmit: true
3+
4+
// #50791
5+
6+
declare function fn1({}?: { x: string }): void;
7+
declare function fn2({ x }?: { x: string }): void;
8+
declare function fn3([]?: [ x: string ]): void;
9+
declare function fn4([ x ]?: [ x: string ]): void;
10+
11+
declare class C1 {
12+
method({}?: { x: string }): void
13+
static method2({}?: { x: string }): void
14+
15+
static field: ({}?: { x: string }) => void
16+
static field2: ({}?: { x: string }) => void
17+
}
18+
19+
interface I1 {
20+
method({}?: { x: string }): void
21+
method2: ({}?: { x: string }) => void
22+
}
23+
24+
type T1 = ({}?: { x: string }) => void
25+
26+
type T2 = {
27+
method({}?: { x: string }): void
28+
method2: ({}?: { x: string }) => void
29+
}
30+
31+
declare const val1: ({}?: { x: string }) => void
32+
33+
declare const val2: {
34+
method({}?: { x: string }): void
35+
method2: ({}?: { x: string }) => void
36+
}

0 commit comments

Comments
 (0)