From b7af3a22840e28e6fa92af20c5ebe1f5e35d0228 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Sat, 28 Mar 2026 21:12:51 -0700 Subject: [PATCH] Port tsgo PR 3276 for testing --- src/compiler/checker.ts | 14 +++++--- ...dingPatternOptionalParameterCached.symbols | 27 +++++++++++++++ ...indingPatternOptionalParameterCached.types | 34 +++++++++++++++++++ .../bindingPatternOptionalParameterCached.ts | 15 ++++++++ 4 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/bindingPatternOptionalParameterCached.symbols create mode 100644 tests/baselines/reference/bindingPatternOptionalParameterCached.types create mode 100644 tests/cases/compiler/bindingPatternOptionalParameterCached.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0567712f11da3..f21d227649663 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11601,11 +11601,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Return the type of a binding element parent. We check SymbolLinks first to see if a type has been // assigned by contextual typing. function getTypeForBindingElementParent(node: BindingElementGrandparent, checkMode: CheckMode) { - if (checkMode !== CheckMode.Normal) { - return getTypeForVariableLikeDeclaration(node, /*includeOptionality*/ false, checkMode); + if (checkMode === CheckMode.Normal) { + // We can use a cached resolved type if no optionality was included in that type. + const symbol = getSymbolOfDeclaration(node); + if (symbol) { + const type = getSymbolLinks(symbol).type; + if (type && !(strictNullChecks && isOptionalDeclaration(node))) { + return type; + } + } } - const symbol = getSymbolOfDeclaration(node); - return symbol && getSymbolLinks(symbol).type || getTypeForVariableLikeDeclaration(node, /*includeOptionality*/ false, checkMode); + return getTypeForVariableLikeDeclaration(node, /*includeOptionality*/ false, checkMode); } function getRestType(source: Type, properties: PropertyName[], symbol: Symbol | undefined): Type { diff --git a/tests/baselines/reference/bindingPatternOptionalParameterCached.symbols b/tests/baselines/reference/bindingPatternOptionalParameterCached.symbols new file mode 100644 index 0000000000000..eeccb919821e1 --- /dev/null +++ b/tests/baselines/reference/bindingPatternOptionalParameterCached.symbols @@ -0,0 +1,27 @@ +//// [tests/cases/compiler/bindingPatternOptionalParameterCached.ts] //// + +=== bindingPatternOptionalParameterCached.ts === +// https://github.com/microsoft/typescript-go/issues/3276 + +// There should be no error in this test, but previously there was because of the +// declaration of mock. Commenting it out would make the error disappear. + +export const mock: I = { +>mock : Symbol(mock, Decl(bindingPatternOptionalParameterCached.ts, 5, 12)) +>I : Symbol(I, Decl(bindingPatternOptionalParameterCached.ts, 7, 2)) + + m: (_) => {}, +>m : Symbol(m, Decl(bindingPatternOptionalParameterCached.ts, 5, 24)) +>_ : Symbol(_, Decl(bindingPatternOptionalParameterCached.ts, 6, 8)) + +}; + +export interface I { +>I : Symbol(I, Decl(bindingPatternOptionalParameterCached.ts, 7, 2)) + + m({ x }?: { x: boolean }): void +>m : Symbol(I.m, Decl(bindingPatternOptionalParameterCached.ts, 9, 20)) +>x : Symbol(x, Decl(bindingPatternOptionalParameterCached.ts, 10, 7)) +>x : Symbol(x, Decl(bindingPatternOptionalParameterCached.ts, 10, 15)) +} + diff --git a/tests/baselines/reference/bindingPatternOptionalParameterCached.types b/tests/baselines/reference/bindingPatternOptionalParameterCached.types new file mode 100644 index 0000000000000..a1205ddc8fdcd --- /dev/null +++ b/tests/baselines/reference/bindingPatternOptionalParameterCached.types @@ -0,0 +1,34 @@ +//// [tests/cases/compiler/bindingPatternOptionalParameterCached.ts] //// + +=== bindingPatternOptionalParameterCached.ts === +// https://github.com/microsoft/typescript-go/issues/3276 + +// There should be no error in this test, but previously there was because of the +// declaration of mock. Commenting it out would make the error disappear. + +export const mock: I = { +>mock : I +> : ^ +>{ m: (_) => {},} : { m: (_: { x: boolean; } | undefined) => void; } +> : ^^^^^^ ^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + m: (_) => {}, +>m : (_: { x: boolean; } | undefined) => void +> : ^ ^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^ +>(_) => {} : (_: { x: boolean; } | undefined) => void +> : ^ ^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^ +>_ : { x: boolean; } | undefined +> : ^^^^^ ^^^^^^^^^^^^^^^ + +}; + +export interface I { + m({ x }?: { x: boolean }): void +>m : ({ x }?: { x: boolean; }) => void +> : ^ ^^^ ^^^^^ +>x : boolean +> : ^^^^^^^ +>x : boolean +> : ^^^^^^^ +} + diff --git a/tests/cases/compiler/bindingPatternOptionalParameterCached.ts b/tests/cases/compiler/bindingPatternOptionalParameterCached.ts new file mode 100644 index 0000000000000..54e0da5444564 --- /dev/null +++ b/tests/cases/compiler/bindingPatternOptionalParameterCached.ts @@ -0,0 +1,15 @@ +// @strict: true +// @noEmit: true + +// https://github.com/microsoft/typescript-go/issues/3276 + +// There should be no error in this test, but previously there was because of the +// declaration of mock. Commenting it out would make the error disappear. + +export const mock: I = { + m: (_) => {}, +}; + +export interface I { + m({ x }?: { x: boolean }): void +}