Fixed false positive errors in empty optional binding patterns in declaration signatures (#50816)

This commit is contained in:
Mateusz Burzyński 2023-03-01 19:58:37 +01:00 committed by GitHub
parent 9c5b09cd21
commit 080f9c1c3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 204 additions and 1 deletions

View File

@ -25119,7 +25119,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
function isInAmbientOrTypeNode(node: Node): boolean {
return !!(node.flags & NodeFlags.Ambient || findAncestor(node, n => isInterfaceDeclaration(n) || isTypeLiteralNode(n)));
return !!(node.flags & NodeFlags.Ambient || findAncestor(node, n => isInterfaceDeclaration(n) || isTypeAliasDeclaration(n) || isTypeLiteralNode(n)));
}
// 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 {
}
// For a binding pattern, validate the initializer and exit
if (isBindingPattern(node.name)) {
if (isInAmbientOrTypeNode(node)) {
return;
}
const needCheckInitializer = hasOnlyExpressionInitializer(node) && node.initializer && node.parent.parent.kind !== SyntaxKind.ForInStatement;
const needCheckWidenedType = !some(node.name.elements, not(isOmittedExpression));
if (needCheckInitializer || needCheckWidenedType) {

View File

@ -0,0 +1,83 @@
=== tests/cases/compiler/emptyOptionalBindingPatternInDeclarationSignature.ts ===
// #50791
declare function fn1({}?: { x: string }): void;
>fn1 : Symbol(fn1, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 0, 0))
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 2, 27))
declare function fn2({ x }?: { x: string }): void;
>fn2 : Symbol(fn2, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 2, 47))
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 3, 22))
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 3, 30))
declare function fn3([]?: [ x: string ]): void;
>fn3 : Symbol(fn3, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 3, 50))
declare function fn4([ x ]?: [ x: string ]): void;
>fn4 : Symbol(fn4, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 4, 47))
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 5, 22))
declare class C1 {
>C1 : Symbol(C1, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 5, 50))
method({}?: { x: string }): void
>method : Symbol(C1.method, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 7, 18))
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 8, 17))
static method2({}?: { x: string }): void
>method2 : Symbol(C1.method2, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 8, 36))
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 9, 25))
static field: ({}?: { x: string }) => void
>field : Symbol(C1.field, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 9, 44))
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 11, 25))
static field2: ({}?: { x: string }) => void
>field2 : Symbol(C1.field2, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 11, 46))
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 12, 26))
}
interface I1 {
>I1 : Symbol(I1, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 13, 1))
method({}?: { x: string }): void
>method : Symbol(I1.method, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 15, 14))
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 16, 17))
method2: ({}?: { x: string }) => void
>method2 : Symbol(I1.method2, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 16, 36))
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 17, 20))
}
type T1 = ({}?: { x: string }) => void
>T1 : Symbol(T1, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 18, 1))
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 20, 17))
type T2 = {
>T2 : Symbol(T2, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 20, 38))
method({}?: { x: string }): void
>method : Symbol(method, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 22, 11))
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 23, 17))
method2: ({}?: { x: string }) => void
>method2 : Symbol(method2, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 23, 36))
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 24, 20))
}
declare const val1: ({}?: { x: string }) => void
>val1 : Symbol(val1, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 27, 13))
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 27, 27))
declare const val2: {
>val2 : Symbol(val2, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 29, 13))
method({}?: { x: string }): void
>method : Symbol(method, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 29, 21))
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 30, 17))
method2: ({}?: { x: string }) => void
>method2 : Symbol(method2, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 30, 36))
>x : Symbol(x, Decl(emptyOptionalBindingPatternInDeclarationSignature.ts, 31, 20))
}

View File

@ -0,0 +1,81 @@
=== tests/cases/compiler/emptyOptionalBindingPatternInDeclarationSignature.ts ===
// #50791
declare function fn1({}?: { x: string }): void;
>fn1 : ({}?: { x: string;}) => void
>x : string
declare function fn2({ x }?: { x: string }): void;
>fn2 : ({ x }?: { x: string;}) => void
>x : string
>x : string
declare function fn3([]?: [ x: string ]): void;
>fn3 : ([]?: [x: string]) => void
declare function fn4([ x ]?: [ x: string ]): void;
>fn4 : ([x]?: [x: string]) => void
>x : string
declare class C1 {
>C1 : C1
method({}?: { x: string }): void
>method : ({}?: { x: string;}) => void
>x : string
static method2({}?: { x: string }): void
>method2 : ({}?: { x: string;}) => void
>x : string
static field: ({}?: { x: string }) => void
>field : ({}?: { x: string;}) => void
>x : string
static field2: ({}?: { x: string }) => void
>field2 : ({}?: { x: string;}) => void
>x : string
}
interface I1 {
method({}?: { x: string }): void
>method : ({}?: { x: string;}) => void
>x : string
method2: ({}?: { x: string }) => void
>method2 : ({}?: { x: string;}) => void
>x : string
}
type T1 = ({}?: { x: string }) => void
>T1 : ({}?: { x: string;}) => void
>x : string
type T2 = {
>T2 : { method({}?: { x: string;}): void; method2: ({}?: { x: string;}) => void; }
method({}?: { x: string }): void
>method : ({}?: { x: string;}) => void
>x : string
method2: ({}?: { x: string }) => void
>method2 : ({}?: { x: string;}) => void
>x : string
}
declare const val1: ({}?: { x: string }) => void
>val1 : ({}?: { x: string;}) => void
>x : string
declare const val2: {
>val2 : { method({}?: { x: string;}): void; method2: ({}?: { x: string;}) => void; }
method({}?: { x: string }): void
>method : ({}?: { x: string;}) => void
>x : string
method2: ({}?: { x: string }) => void
>method2 : ({}?: { x: string;}) => void
>x : string
}

View File

@ -0,0 +1,36 @@
// @strict: true
// @noEmit: true
// #50791
declare function fn1({}?: { x: string }): void;
declare function fn2({ x }?: { x: string }): void;
declare function fn3([]?: [ x: string ]): void;
declare function fn4([ x ]?: [ x: string ]): void;
declare class C1 {
method({}?: { x: string }): void
static method2({}?: { x: string }): void
static field: ({}?: { x: string }) => void
static field2: ({}?: { x: string }) => void
}
interface I1 {
method({}?: { x: string }): void
method2: ({}?: { x: string }) => void
}
type T1 = ({}?: { x: string }) => void
type T2 = {
method({}?: { x: string }): void
method2: ({}?: { x: string }) => void
}
declare const val1: ({}?: { x: string }) => void
declare const val2: {
method({}?: { x: string }): void
method2: ({}?: { x: string }) => void
}