From 94a0a5a38b8774744c66b460c015a7b91f381401 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 11 Jul 2026 01:15:17 +0200 Subject: [PATCH 1/9] Keep dependent destructuring narrowing during re-entrant checks --- internal/checker/checker.go | 37 ++-- internal/checker/types.go | 1 - ...ntDestructuringOverloadedAssertion.symbols | 58 +++++ ...dentDestructuringOverloadedAssertion.types | 63 ++++++ ...ntDestructuredVariablesNoCrash1.errors.txt | 24 ++ .../dependentDestructuredVariablesNoCrash1.js | 18 ++ ...ndentDestructuredVariablesNoCrash1.symbols | 14 ++ ...pendentDestructuredVariablesNoCrash1.types | 14 ++ ...ntDestructuredVariablesNoCrash2.errors.txt | 25 +++ .../dependentDestructuredVariablesNoCrash2.js | 15 ++ ...ndentDestructuredVariablesNoCrash2.symbols | 11 + ...pendentDestructuredVariablesNoCrash2.types | 11 + ...ntDestructuredVariablesNoCrash3.errors.txt | 27 +++ .../dependentDestructuredVariablesNoCrash3.js | 16 ++ ...ndentDestructuredVariablesNoCrash3.symbols | 17 ++ ...pendentDestructuredVariablesNoCrash3.types | 26 +++ ...riablesRefereinceInDeclaration1.errors.txt | 149 +++++++++++++ ...dVariablesRefereinceInDeclaration1.symbols | 175 +++++++++++++++ ...redVariablesRefereinceInDeclaration1.types | 205 ++++++++++++++++++ ...pendentDestructuringOverloadedAssertion.ts | 19 ++ .../dependentDestructuredVariablesNoCrash1.ts | 8 + .../dependentDestructuredVariablesNoCrash2.ts | 6 + .../dependentDestructuredVariablesNoCrash3.ts | 6 + ...cturedVariablesRefereinceInDeclaration1.ts | 69 ++++++ 24 files changed, 992 insertions(+), 22 deletions(-) create mode 100644 testdata/baselines/reference/compiler/controlFlowDependentDestructuringOverloadedAssertion.symbols create mode 100644 testdata/baselines/reference/compiler/controlFlowDependentDestructuringOverloadedAssertion.types create mode 100644 testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash1.errors.txt create mode 100644 testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash1.js create mode 100644 testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash1.symbols create mode 100644 testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash1.types create mode 100644 testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash2.errors.txt create mode 100644 testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash2.js create mode 100644 testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash2.symbols create mode 100644 testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash2.types create mode 100644 testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash3.errors.txt create mode 100644 testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash3.js create mode 100644 testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash3.symbols create mode 100644 testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash3.types create mode 100644 testdata/baselines/reference/conformance/dependentDestructuredVariablesRefereinceInDeclaration1.errors.txt create mode 100644 testdata/baselines/reference/conformance/dependentDestructuredVariablesRefereinceInDeclaration1.symbols create mode 100644 testdata/baselines/reference/conformance/dependentDestructuredVariablesRefereinceInDeclaration1.types create mode 100644 testdata/tests/cases/compiler/controlFlowDependentDestructuringOverloadedAssertion.ts create mode 100644 testdata/tests/cases/conformance/controlFlow/dependentDestructuredVariablesNoCrash1.ts create mode 100644 testdata/tests/cases/conformance/controlFlow/dependentDestructuredVariablesNoCrash2.ts create mode 100644 testdata/tests/cases/conformance/controlFlow/dependentDestructuredVariablesNoCrash3.ts create mode 100644 testdata/tests/cases/conformance/controlFlow/dependentDestructuredVariablesRefereinceInDeclaration1.ts diff --git a/internal/checker/checker.go b/internal/checker/checker.go index b639d488e44..82db8b92c7c 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -13655,7 +13655,7 @@ func (c *Checker) isInPropertyInitializerOrClassStaticBlock(node *ast.Node, igno func (c *Checker) getNarrowedTypeOfSymbol(symbol *ast.Symbol, location *ast.Node) *Type { t := c.getTypeOfSymbol(symbol) declaration := symbol.ValueDeclaration - if declaration != nil { + if declaration != nil && !ast.GetRootDeclaration(declaration).Loc.ContainsInclusive(location.Pos()) { switch { // If we have a non-rest binding element with no initializer declared as a const variable or a const-like // parameter (a parameter for which there are no assignments in the function body), and if the parent type @@ -13684,27 +13684,22 @@ func (c *Checker) getNarrowedTypeOfSymbol(symbol *ast.Symbol, location *ast.Node parent := declaration.Parent.Parent rootDeclaration := ast.GetRootDeclaration(parent) if ast.IsVariableDeclaration(rootDeclaration) && c.getCombinedNodeFlagsCached(rootDeclaration)&ast.NodeFlagsConstant != 0 || ast.IsParameterDeclaration(rootDeclaration) { - links := c.nodeLinks.Get(parent) - if links.flags&NodeCheckFlagsInCheckIdentifier == 0 { - links.flags |= NodeCheckFlagsInCheckIdentifier - parentType := c.getTypeForBindingElementParent(parent, CheckModeNormal) - var parentTypeConstraint *Type - if parentType != nil { - parentTypeConstraint = c.mapType(parentType, c.getBaseConstraintOrType) - } - if parentTypeConstraint != nil && parentTypeConstraint.flags&TypeFlagsUnion != 0 && !(ast.IsParameterDeclaration(rootDeclaration) && c.isSomeSymbolAssigned(rootDeclaration)) { - pattern := declaration.Parent - narrowedType := c.getFlowTypeOfReferenceEx(pattern, parentTypeConstraint, parentTypeConstraint, nil /*flowContainer*/, getFlowNodeOfNode(location)) - if narrowedType.flags&TypeFlagsNever != 0 { - t = c.neverType - } else { - // Destructurings are validated against the parent type elsewhere. Here we disable tuple bounds - // checks because the narrowed type may have lower arity than the full parent type. For example, - // for the declaration [x, y]: [1, 2] | [3], we may have narrowed the parent type to just [3]. - t = c.getBindingElementTypeFromParentType(declaration, narrowedType, true /*noTupleBoundsCheck*/) - } + parentType := c.getTypeForBindingElementParent(parent, CheckModeNormal) + var parentTypeConstraint *Type + if parentType != nil { + parentTypeConstraint = c.mapType(parentType, c.getBaseConstraintOrType) + } + if parentTypeConstraint != nil && parentTypeConstraint.flags&TypeFlagsUnion != 0 && !(ast.IsParameterDeclaration(rootDeclaration) && c.isSomeSymbolAssigned(rootDeclaration)) { + pattern := declaration.Parent + narrowedType := c.getFlowTypeOfReferenceEx(pattern, parentTypeConstraint, parentTypeConstraint, nil /*flowContainer*/, getFlowNodeOfNode(location)) + if narrowedType.flags&TypeFlagsNever != 0 { + t = c.neverType + } else { + // Destructurings are validated against the parent type elsewhere. Here we disable tuple bounds + // checks because the narrowed type may have lower arity than the full parent type. For example, + // for the declaration [x, y]: [1, 2] | [3], we may have narrowed the parent type to just [3]. + t = c.getBindingElementTypeFromParentType(declaration, narrowedType, true /*noTupleBoundsCheck*/) } - links.flags &^= NodeCheckFlagsInCheckIdentifier } } // If we have a const-like parameter with no type annotation or initializer, and if the parameter is contextually diff --git a/internal/checker/types.go b/internal/checker/types.go index bd13420922e..4d63c594b84 100644 --- a/internal/checker/types.go +++ b/internal/checker/types.go @@ -352,7 +352,6 @@ const ( NodeCheckFlagsAssignmentsMarked NodeCheckFlags = 1 << 17 // Parameter assignments have been marked NodeCheckFlagsContainsClassWithPrivateIdentifiers NodeCheckFlags = 1 << 20 // Marked on all block-scoped containers containing a class with private identifiers. NodeCheckFlagsContainsSuperPropertyInStaticInitializer NodeCheckFlags = 1 << 21 // Marked on all block-scoped containers containing a static initializer with 'super.x' or 'super[x]'. - NodeCheckFlagsInCheckIdentifier NodeCheckFlags = 1 << 22 NodeCheckFlagsInitializerIsUndefined NodeCheckFlags = 1 << 24 NodeCheckFlagsInitializerIsUndefinedComputed NodeCheckFlags = 1 << 25 ) diff --git a/testdata/baselines/reference/compiler/controlFlowDependentDestructuringOverloadedAssertion.symbols b/testdata/baselines/reference/compiler/controlFlowDependentDestructuringOverloadedAssertion.symbols new file mode 100644 index 00000000000..4f32ef64f38 --- /dev/null +++ b/testdata/baselines/reference/compiler/controlFlowDependentDestructuringOverloadedAssertion.symbols @@ -0,0 +1,58 @@ +//// [tests/cases/compiler/controlFlowDependentDestructuringOverloadedAssertion.ts] //// + +=== controlFlowDependentDestructuringOverloadedAssertion.ts === +// https://github.com/microsoft/typescript-go/issues/4572 + +type State = +>State : Symbol(State, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 0, 0)) + + | { status: "ready"; payload: { value?: string } } +>status : Symbol(status, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 3, 5)) +>payload : Symbol(payload, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 3, 22)) +>value : Symbol(value, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 3, 33)) + + | { status: "pending"; payload?: undefined }; +>status : Symbol(status, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 4, 5)) +>payload : Symbol(payload, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 4, 24)) + +declare function getState(): State; +>getState : Symbol(getState, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 4, 47)) +>State : Symbol(State, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 0, 0)) + +declare function assert(condition: boolean): asserts condition; +>assert : Symbol(assert, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 6, 35), Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 7, 63)) +>condition : Symbol(condition, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 7, 24)) +>condition : Symbol(condition, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 7, 24)) + +declare function assert(condition: boolean, message: string): asserts condition; +>assert : Symbol(assert, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 6, 35), Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 7, 63)) +>condition : Symbol(condition, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 8, 24)) +>message : Symbol(message, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 8, 43)) +>condition : Symbol(condition, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 8, 24)) + +const readValue = () => { +>readValue : Symbol(readValue, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 10, 5)) + + const { status, payload } = getState(); +>status : Symbol(status, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 11, 9)) +>payload : Symbol(payload, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 11, 17)) +>getState : Symbol(getState, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 4, 47)) + + if (status !== "ready") throw new Error("Value is not ready."); +>status : Symbol(status, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 11, 9)) +>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2022.error.d.ts, --, --)) + + assert(payload.value !== undefined); +>assert : Symbol(assert, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 6, 35), Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 7, 63)) +>payload.value : Symbol(value, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 3, 33)) +>payload : Symbol(payload, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 11, 17)) +>value : Symbol(value, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 3, 33)) +>undefined : Symbol(undefined) + + return payload.value; +>payload.value : Symbol(value, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 3, 33)) +>payload : Symbol(payload, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 11, 17)) +>value : Symbol(value, Decl(controlFlowDependentDestructuringOverloadedAssertion.ts, 3, 33)) + +}; + diff --git a/testdata/baselines/reference/compiler/controlFlowDependentDestructuringOverloadedAssertion.types b/testdata/baselines/reference/compiler/controlFlowDependentDestructuringOverloadedAssertion.types new file mode 100644 index 00000000000..1ed6a59ad2a --- /dev/null +++ b/testdata/baselines/reference/compiler/controlFlowDependentDestructuringOverloadedAssertion.types @@ -0,0 +1,63 @@ +//// [tests/cases/compiler/controlFlowDependentDestructuringOverloadedAssertion.ts] //// + +=== controlFlowDependentDestructuringOverloadedAssertion.ts === +// https://github.com/microsoft/typescript-go/issues/4572 + +type State = +>State : State + + | { status: "ready"; payload: { value?: string } } +>status : "ready" +>payload : { value?: string; } +>value : string | undefined + + | { status: "pending"; payload?: undefined }; +>status : "pending" +>payload : undefined + +declare function getState(): State; +>getState : () => State + +declare function assert(condition: boolean): asserts condition; +>assert : { (condition: boolean): asserts condition; (condition: boolean, message: string): asserts condition; } +>condition : boolean + +declare function assert(condition: boolean, message: string): asserts condition; +>assert : { (condition: boolean): asserts condition; (condition: boolean, message: string): asserts condition; } +>condition : boolean +>message : string + +const readValue = () => { +>readValue : () => string +>() => { const { status, payload } = getState(); if (status !== "ready") throw new Error("Value is not ready."); assert(payload.value !== undefined); return payload.value;} : () => string + + const { status, payload } = getState(); +>status : "pending" | "ready" +>payload : { value?: string; } | undefined +>getState() : State +>getState : () => State + + if (status !== "ready") throw new Error("Value is not ready."); +>status !== "ready" : boolean +>status : "pending" | "ready" +>"ready" : "ready" +>new Error("Value is not ready.") : Error +>Error : ErrorConstructor +>"Value is not ready." : "Value is not ready." + + assert(payload.value !== undefined); +>assert(payload.value !== undefined) : void +>assert : { (condition: boolean): asserts condition; (condition: boolean, message: string): asserts condition; } +>payload.value !== undefined : boolean +>payload.value : string | undefined +>payload : { value?: string; } +>value : string | undefined +>undefined : undefined + + return payload.value; +>payload.value : string +>payload : { value?: string; } +>value : string + +}; + diff --git a/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash1.errors.txt b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash1.errors.txt new file mode 100644 index 00000000000..47eb27c9423 --- /dev/null +++ b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash1.errors.txt @@ -0,0 +1,24 @@ +dependentDestructuredVariablesNoCrash1.ts(3,10): error TS7010: 'f', which lacks return-type annotation, implicitly has an 'any' return type. +dependentDestructuredVariablesNoCrash1.ts(5,12): error TS1015: Parameter cannot have question mark and initializer. +dependentDestructuredVariablesNoCrash1.ts(5,12): error TS2488: Type '() => any' must have a '[Symbol.iterator]()' method that returns an iterator. +dependentDestructuredVariablesNoCrash1.ts(5,20): error TS7022: 'undefined' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. +dependentDestructuredVariablesNoCrash1.ts(5,45): error TS2373: Parameter '[first, undefined]' cannot reference identifier 'undefined' declared after it. + + +==== dependentDestructuredVariablesNoCrash1.ts (5 errors) ==== + // https://github.com/microsoft/TypeScript/issues/63044 + + function f() + ~ +!!! error TS7010: 'f', which lacks return-type annotation, implicitly has an 'any' return type. + + function f([first, undefined]?: () => any = undefined) {} + ~~~~~~~~~~~~~~~~~~ +!!! error TS1015: Parameter cannot have question mark and initializer. + ~~~~~~~~~~~~~~~~~~ +!!! error TS2488: Type '() => any' must have a '[Symbol.iterator]()' method that returns an iterator. + ~~~~~~~~~ +!!! error TS7022: 'undefined' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. + ~~~~~~~~~ +!!! error TS2373: Parameter '[first, undefined]' cannot reference identifier 'undefined' declared after it. + \ No newline at end of file diff --git a/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash1.js b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash1.js new file mode 100644 index 00000000000..4305a9bb5ea --- /dev/null +++ b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash1.js @@ -0,0 +1,18 @@ +//// [tests/cases/conformance/controlFlow/dependentDestructuredVariablesNoCrash1.ts] //// + +//// [dependentDestructuredVariablesNoCrash1.ts] +// https://github.com/microsoft/TypeScript/issues/63044 + +function f() + +function f([first, undefined]?: () => any = undefined) {} + + +//// [dependentDestructuredVariablesNoCrash1.js] +"use strict"; +// https://github.com/microsoft/TypeScript/issues/63044 +function f([first, undefined] = undefined) { } + + +//// [dependentDestructuredVariablesNoCrash1.d.ts] +declare function f(): any; diff --git a/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash1.symbols b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash1.symbols new file mode 100644 index 00000000000..f757596002e --- /dev/null +++ b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash1.symbols @@ -0,0 +1,14 @@ +//// [tests/cases/conformance/controlFlow/dependentDestructuredVariablesNoCrash1.ts] //// + +=== dependentDestructuredVariablesNoCrash1.ts === +// https://github.com/microsoft/TypeScript/issues/63044 + +function f() +>f : Symbol(f, Decl(dependentDestructuredVariablesNoCrash1.ts, 0, 0), Decl(dependentDestructuredVariablesNoCrash1.ts, 2, 12)) + +function f([first, undefined]?: () => any = undefined) {} +>f : Symbol(f, Decl(dependentDestructuredVariablesNoCrash1.ts, 0, 0), Decl(dependentDestructuredVariablesNoCrash1.ts, 2, 12)) +>first : Symbol(first, Decl(dependentDestructuredVariablesNoCrash1.ts, 4, 12)) +>undefined : Symbol(undefined, Decl(dependentDestructuredVariablesNoCrash1.ts, 4, 18)) +>undefined : Symbol(undefined, Decl(dependentDestructuredVariablesNoCrash1.ts, 4, 18)) + diff --git a/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash1.types b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash1.types new file mode 100644 index 00000000000..9b37eb3d55b --- /dev/null +++ b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash1.types @@ -0,0 +1,14 @@ +//// [tests/cases/conformance/controlFlow/dependentDestructuredVariablesNoCrash1.ts] //// + +=== dependentDestructuredVariablesNoCrash1.ts === +// https://github.com/microsoft/TypeScript/issues/63044 + +function f() +>f : () => any + +function f([first, undefined]?: () => any = undefined) {} +>f : () => any +>first : any +>undefined : any +>undefined : any + diff --git a/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash2.errors.txt b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash2.errors.txt new file mode 100644 index 00000000000..84f6a68a8bf --- /dev/null +++ b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash2.errors.txt @@ -0,0 +1,25 @@ +dependentDestructuredVariablesNoCrash2.ts(3,9): error TS7010: '(Missing)', which lacks return-type annotation, implicitly has an 'any' return type. +dependentDestructuredVariablesNoCrash2.ts(3,10): error TS1003: Identifier expected. +dependentDestructuredVariablesNoCrash2.ts(3,11): error TS2488: Type 'string | undefined' must have a '[Symbol.iterator]()' method that returns an iterator. +dependentDestructuredVariablesNoCrash2.ts(3,11): error TS2371: A parameter initializer is only allowed in a function or constructor implementation. +dependentDestructuredVariablesNoCrash2.ts(3,12): error TS7022: 'undefined' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. +dependentDestructuredVariablesNoCrash2.ts(3,54): error TS2373: Parameter '[undefined, unknown]' cannot reference identifier 'undefined' declared after it. + + +==== dependentDestructuredVariablesNoCrash2.ts (6 errors) ==== + // https://github.com/microsoft/TypeScript/issues/63091 + + function ([undefined, unknown]: string | undefined = undefined) + +!!! error TS7010: '(Missing)', which lacks return-type annotation, implicitly has an 'any' return type. + ~ +!!! error TS1003: Identifier expected. + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2488: Type 'string | undefined' must have a '[Symbol.iterator]()' method that returns an iterator. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2371: A parameter initializer is only allowed in a function or constructor implementation. + ~~~~~~~~~ +!!! error TS7022: 'undefined' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. + ~~~~~~~~~ +!!! error TS2373: Parameter '[undefined, unknown]' cannot reference identifier 'undefined' declared after it. + \ No newline at end of file diff --git a/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash2.js b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash2.js new file mode 100644 index 00000000000..c52676c55b4 --- /dev/null +++ b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash2.js @@ -0,0 +1,15 @@ +//// [tests/cases/conformance/controlFlow/dependentDestructuredVariablesNoCrash2.ts] //// + +//// [dependentDestructuredVariablesNoCrash2.ts] +// https://github.com/microsoft/TypeScript/issues/63091 + +function ([undefined, unknown]: string | undefined = undefined) + + +//// [dependentDestructuredVariablesNoCrash2.js] +"use strict"; +// https://github.com/microsoft/TypeScript/issues/63091 + + +//// [dependentDestructuredVariablesNoCrash2.d.ts] +declare function ([undefined, unknown]?: string | undefined): any; diff --git a/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash2.symbols b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash2.symbols new file mode 100644 index 00000000000..9d6f183dd8d --- /dev/null +++ b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash2.symbols @@ -0,0 +1,11 @@ +//// [tests/cases/conformance/controlFlow/dependentDestructuredVariablesNoCrash2.ts] //// + +=== dependentDestructuredVariablesNoCrash2.ts === +// https://github.com/microsoft/TypeScript/issues/63091 + +function ([undefined, unknown]: string | undefined = undefined) +> : Symbol((Missing), Decl(dependentDestructuredVariablesNoCrash2.ts, 0, 0)) +>undefined : Symbol(undefined, Decl(dependentDestructuredVariablesNoCrash2.ts, 2, 11)) +>unknown : Symbol(unknown, Decl(dependentDestructuredVariablesNoCrash2.ts, 2, 21)) +>undefined : Symbol(undefined, Decl(dependentDestructuredVariablesNoCrash2.ts, 2, 11)) + diff --git a/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash2.types b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash2.types new file mode 100644 index 00000000000..b2524e27ef7 --- /dev/null +++ b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash2.types @@ -0,0 +1,11 @@ +//// [tests/cases/conformance/controlFlow/dependentDestructuredVariablesNoCrash2.ts] //// + +=== dependentDestructuredVariablesNoCrash2.ts === +// https://github.com/microsoft/TypeScript/issues/63091 + +function ([undefined, unknown]: string | undefined = undefined) +> : ([undefined, unknown]?: string | undefined) => any +>undefined : any +>unknown : any +>undefined : any + diff --git a/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash3.errors.txt b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash3.errors.txt new file mode 100644 index 00000000000..3fc104f3523 --- /dev/null +++ b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash3.errors.txt @@ -0,0 +1,27 @@ +error TS-1: Pre-emit (6) and post-emit (5) diagnostic counts do not match! This can indicate that a semantic _error_ was added by the emit resolver - such an error may not be reflected on the command line or in the editor, but may be captured in a baseline here! +dependentDestructuredVariablesNoCrash3.ts(3,30): error TS7022: 'string' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. +dependentDestructuredVariablesNoCrash3.ts(3,69): error TS2593: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i --save-dev @types/jest` or `npm i --save-dev @types/mocha` and then add 'jest' or 'mocha' to the types field in your tsconfig. +dependentDestructuredVariablesNoCrash3.ts(3,86): error TS2448: Block-scoped variable 'string' used before its declaration. +dependentDestructuredVariablesNoCrash3.ts(3,95): error TS1109: Expression expected. +dependentDestructuredVariablesNoCrash3.ts(3,97): error TS2339: Property 'ranges' does not exist on type 'boolean'. + + +!!! error TS-1: Pre-emit (6) and post-emit (5) diagnostic counts do not match! This can indicate that a semantic _error_ was added by the emit resolver - such an error may not be reflected on the command line or in the editor, but may be captured in a baseline here! +!!! related TS-1: The excess diagnostics are: +!!! related TS2488 dependentDestructuredVariablesNoCrash3.ts:3:7: Type 'boolean' must have a '[Symbol.iterator]()' method that returns an iterator. +==== dependentDestructuredVariablesNoCrash3.ts (5 errors) ==== + // https://github.com/microsoft/TypeScript/issues/63093 + + const [r0Def, r0, r1Def, as, string, r1, r2, r3Def, r3]: boolean = (test as number < string > ).ranges(); + ~~~~~~ +!!! error TS7022: 'string' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. + ~~~~ +!!! error TS2593: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i --save-dev @types/jest` or `npm i --save-dev @types/mocha` and then add 'jest' or 'mocha' to the types field in your tsconfig. + ~~~~~~ +!!! error TS2448: Block-scoped variable 'string' used before its declaration. +!!! related TS2728 dependentDestructuredVariablesNoCrash3.ts:3:30: 'string' is declared here. + ~ +!!! error TS1109: Expression expected. + ~~~~~~ +!!! error TS2339: Property 'ranges' does not exist on type 'boolean'. + \ No newline at end of file diff --git a/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash3.js b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash3.js new file mode 100644 index 00000000000..08565e0aa66 --- /dev/null +++ b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash3.js @@ -0,0 +1,16 @@ +//// [tests/cases/conformance/controlFlow/dependentDestructuredVariablesNoCrash3.ts] //// + +//// [dependentDestructuredVariablesNoCrash3.ts] +// https://github.com/microsoft/TypeScript/issues/63093 + +const [r0Def, r0, r1Def, as, string, r1, r2, r3Def, r3]: boolean = (test as number < string > ).ranges(); + + +//// [dependentDestructuredVariablesNoCrash3.js] +"use strict"; +// https://github.com/microsoft/TypeScript/issues/63093 +const [r0Def, r0, r1Def, as, string, r1, r2, r3Def, r3] = (test < string > ).ranges(); + + +//// [dependentDestructuredVariablesNoCrash3.d.ts] +declare const r0Def: any, r0: any, r1Def: any, as: any, string: any, r1: any, r2: any, r3Def: any, r3: any; diff --git a/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash3.symbols b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash3.symbols new file mode 100644 index 00000000000..0da8e00245b --- /dev/null +++ b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash3.symbols @@ -0,0 +1,17 @@ +//// [tests/cases/conformance/controlFlow/dependentDestructuredVariablesNoCrash3.ts] //// + +=== dependentDestructuredVariablesNoCrash3.ts === +// https://github.com/microsoft/TypeScript/issues/63093 + +const [r0Def, r0, r1Def, as, string, r1, r2, r3Def, r3]: boolean = (test as number < string > ).ranges(); +>r0Def : Symbol(r0Def, Decl(dependentDestructuredVariablesNoCrash3.ts, 2, 7)) +>r0 : Symbol(r0, Decl(dependentDestructuredVariablesNoCrash3.ts, 2, 13)) +>r1Def : Symbol(r1Def, Decl(dependentDestructuredVariablesNoCrash3.ts, 2, 17)) +>as : Symbol(as, Decl(dependentDestructuredVariablesNoCrash3.ts, 2, 24)) +>string : Symbol(string, Decl(dependentDestructuredVariablesNoCrash3.ts, 2, 28)) +>r1 : Symbol(r1, Decl(dependentDestructuredVariablesNoCrash3.ts, 2, 36)) +>r2 : Symbol(r2, Decl(dependentDestructuredVariablesNoCrash3.ts, 2, 40)) +>r3Def : Symbol(r3Def, Decl(dependentDestructuredVariablesNoCrash3.ts, 2, 44)) +>r3 : Symbol(r3, Decl(dependentDestructuredVariablesNoCrash3.ts, 2, 51)) +>string : Symbol(string, Decl(dependentDestructuredVariablesNoCrash3.ts, 2, 28)) + diff --git a/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash3.types b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash3.types new file mode 100644 index 00000000000..e49fcca5d4d --- /dev/null +++ b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash3.types @@ -0,0 +1,26 @@ +//// [tests/cases/conformance/controlFlow/dependentDestructuredVariablesNoCrash3.ts] //// + +=== dependentDestructuredVariablesNoCrash3.ts === +// https://github.com/microsoft/TypeScript/issues/63093 + +const [r0Def, r0, r1Def, as, string, r1, r2, r3Def, r3]: boolean = (test as number < string > ).ranges(); +>r0Def : any +>r0 : any +>r1Def : any +>as : any +>string : any +>r1 : any +>r2 : any +>r3Def : any +>r3 : any +>(test as number < string > ).ranges() : any +>(test as number < string > ).ranges : any +>(test as number < string > ) : boolean +>test as number < string > : boolean +>test as number < string : boolean +>test as number : number +>test : any +>string : any +> : any +>ranges : any + diff --git a/testdata/baselines/reference/conformance/dependentDestructuredVariablesRefereinceInDeclaration1.errors.txt b/testdata/baselines/reference/conformance/dependentDestructuredVariablesRefereinceInDeclaration1.errors.txt new file mode 100644 index 00000000000..f38d9d18394 --- /dev/null +++ b/testdata/baselines/reference/conformance/dependentDestructuredVariablesRefereinceInDeclaration1.errors.txt @@ -0,0 +1,149 @@ +dependentDestructuredVariablesRefereinceInDeclaration1.ts(4,9): error TS2322: Type '{ c: number; f: any; }' is not assignable to type 'string | number'. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(4,11): error TS2339: Property 'c' does not exist on type 'string | number'. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(4,14): error TS2339: Property 'f' does not exist on type 'string | number'. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(4,14): error TS7022: 'f' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(4,45): error TS2448: Block-scoped variable 'f' used before its declaration. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(9,9): error TS2322: Type '{ c: number; f: () => any; }' is not assignable to type 'string | number'. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(9,11): error TS2339: Property 'c' does not exist on type 'string | number'. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(9,14): error TS2339: Property 'f' does not exist on type 'string | number'. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(14,9): error TS2322: Type '{ c: number; f: number; g: number; }' is not assignable to type 'string | number'. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(14,11): error TS2339: Property 'c' does not exist on type 'string | number'. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(14,14): error TS2339: Property 'f' does not exist on type 'string | number'. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(14,17): error TS2339: Property 'g' does not exist on type 'string | number'. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(20,9): error TS2322: Type '{ c: number; f: number; }' is not assignable to type 'string | number'. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(20,11): error TS2339: Property 'c' does not exist on type 'string | number'. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(20,14): error TS2339: Property 'f' does not exist on type 'string | number'. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(20,14): error TS2451: Cannot redeclare block-scoped variable 'f'. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(20,17): error TS2339: Property 'f' does not exist on type 'string | number'. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(20,17): error TS2451: Cannot redeclare block-scoped variable 'f'. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(25,9): error TS2322: Type '{ c: number; f: number; }' is not assignable to type 'string | number'. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(25,11): error TS2339: Property 'c' does not exist on type 'string | number'. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(25,14): error TS2339: Property 'f' does not exist on type 'string | number'. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(25,17): error TS2339: Property 'f' does not exist on type 'string | number'. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(30,14): error TS7022: 'f' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(30,71): error TS2448: Block-scoped variable 'f' used before its declaration. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(58,14): error TS2451: Cannot redeclare block-scoped variable 'f'. +dependentDestructuredVariablesRefereinceInDeclaration1.ts(58,17): error TS2451: Cannot redeclare block-scoped variable 'f'. + + +==== dependentDestructuredVariablesRefereinceInDeclaration1.ts (26 errors) ==== + // https://github.com/microsoft/TypeScript/issues/62993 + + { + const { c, f }: string | number = { c: 0, f }; + ~~~~~~~~ +!!! error TS2322: Type '{ c: number; f: any; }' is not assignable to type 'string | number'. + ~ +!!! error TS2339: Property 'c' does not exist on type 'string | number'. + ~ +!!! error TS2339: Property 'f' does not exist on type 'string | number'. + ~ +!!! error TS7022: 'f' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. + ~ +!!! error TS2448: Block-scoped variable 'f' used before its declaration. +!!! related TS2728 dependentDestructuredVariablesRefereinceInDeclaration1.ts:4:14: 'f' is declared here. + f; + } + + { + const { c, f }: string | number = { c: 0, f: () => f }; + ~~~~~~~~ +!!! error TS2322: Type '{ c: number; f: () => any; }' is not assignable to type 'string | number'. + ~ +!!! error TS2339: Property 'c' does not exist on type 'string | number'. + ~ +!!! error TS2339: Property 'f' does not exist on type 'string | number'. + f; + } + + { + const { c, f, g = f }: string | number = { c: 0, f: 0, g: 0 }; + ~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ c: number; f: number; g: number; }' is not assignable to type 'string | number'. + ~ +!!! error TS2339: Property 'c' does not exist on type 'string | number'. + ~ +!!! error TS2339: Property 'f' does not exist on type 'string | number'. + ~ +!!! error TS2339: Property 'g' does not exist on type 'string | number'. + f; + g; + } + + { + const { c, f, f }: string | number = { c: 0, f: 0 }; + ~~~~~~~~~~~ +!!! error TS2322: Type '{ c: number; f: number; }' is not assignable to type 'string | number'. + ~ +!!! error TS2339: Property 'c' does not exist on type 'string | number'. + ~ +!!! error TS2339: Property 'f' does not exist on type 'string | number'. + ~ +!!! error TS2451: Cannot redeclare block-scoped variable 'f'. + ~ +!!! error TS2339: Property 'f' does not exist on type 'string | number'. + ~ +!!! error TS2451: Cannot redeclare block-scoped variable 'f'. + f; + } + + { + const { c, f, f: g }: string | number = { c: 0, f: 0 }; + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ c: number; f: number; }' is not assignable to type 'string | number'. + ~ +!!! error TS2339: Property 'c' does not exist on type 'string | number'. + ~ +!!! error TS2339: Property 'f' does not exist on type 'string | number'. + ~ +!!! error TS2339: Property 'f' does not exist on type 'string | number'. + g; + } + + { + const { c, f }: { c: 0; f: number } | { c: 1; f: string } = { c: 0, f }; + ~ +!!! error TS7022: 'f' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. + ~ +!!! error TS2448: Block-scoped variable 'f' used before its declaration. +!!! related TS2728 dependentDestructuredVariablesRefereinceInDeclaration1.ts:30:14: 'f' is declared here. + f; + } + + { + const { c, f }: { c: 0; f: () => unknown } | { c: 1; f: string } = { + c: 0, + f: () => f, + }; + f; + } + + { + const { + c, + f, + g = f, + }: + | { c: 0; f: bigint; g?: bigint | number } + | { c: 1; f: number; g: string } = { + c: 0, + f: 10n, + }; + f; + g; + } + + { + const { c, f, f }: { c: 0; f: number } | { c: 1; f: string } = { c: 0, f: 0 }; + ~ +!!! error TS2451: Cannot redeclare block-scoped variable 'f'. + ~ +!!! error TS2451: Cannot redeclare block-scoped variable 'f'. + f; + } + + { + const { c, f, f: g }: { c: 0; f: number } | { c: 1; f: string } = { c: 0, f: 0 }; + g; + } + \ No newline at end of file diff --git a/testdata/baselines/reference/conformance/dependentDestructuredVariablesRefereinceInDeclaration1.symbols b/testdata/baselines/reference/conformance/dependentDestructuredVariablesRefereinceInDeclaration1.symbols new file mode 100644 index 00000000000..b370d5ccbb6 --- /dev/null +++ b/testdata/baselines/reference/conformance/dependentDestructuredVariablesRefereinceInDeclaration1.symbols @@ -0,0 +1,175 @@ +//// [tests/cases/conformance/controlFlow/dependentDestructuredVariablesRefereinceInDeclaration1.ts] //// + +=== dependentDestructuredVariablesRefereinceInDeclaration1.ts === +// https://github.com/microsoft/TypeScript/issues/62993 + +{ + const { c, f }: string | number = { c: 0, f }; +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 3, 9)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 3, 12)) +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 3, 37)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 3, 43)) + + f; +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 3, 12)) +} + +{ + const { c, f }: string | number = { c: 0, f: () => f }; +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 8, 9)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 8, 12)) +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 8, 37)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 8, 43)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 8, 12)) + + f; +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 8, 12)) +} + +{ + const { c, f, g = f }: string | number = { c: 0, f: 0, g: 0 }; +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 13, 9)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 13, 12)) +>g : Symbol(g, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 13, 15)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 13, 12)) +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 13, 44)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 13, 50)) +>g : Symbol(g, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 13, 56)) + + f; +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 13, 12)) + + g; +>g : Symbol(g, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 13, 15)) +} + +{ + const { c, f, f }: string | number = { c: 0, f: 0 }; +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 19, 9)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 19, 12)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 19, 15)) +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 19, 40)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 19, 46)) + + f; +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 19, 12)) +} + +{ + const { c, f, f: g }: string | number = { c: 0, f: 0 }; +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 24, 9)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 24, 12)) +>g : Symbol(g, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 24, 15)) +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 24, 43)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 24, 49)) + + g; +>g : Symbol(g, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 24, 15)) +} + +{ + const { c, f }: { c: 0; f: number } | { c: 1; f: string } = { c: 0, f }; +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 29, 9)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 29, 12)) +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 29, 19)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 29, 25)) +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 29, 41)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 29, 47)) +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 29, 63)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 29, 69)) + + f; +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 29, 12)) +} + +{ + const { c, f }: { c: 0; f: () => unknown } | { c: 1; f: string } = { +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 34, 9)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 34, 12)) +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 34, 19)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 34, 25)) +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 34, 48)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 34, 54)) + + c: 0, +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 34, 70)) + + f: () => f, +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 35, 9)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 34, 12)) + + }; + f; +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 34, 12)) +} + +{ + const { + c, +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 42, 9)) + + f, +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 43, 6)) + + g = f, +>g : Symbol(g, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 44, 6)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 43, 6)) + + }: + | { c: 0; f: bigint; g?: bigint | number } +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 47, 7)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 47, 13)) +>g : Symbol(g, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 47, 24)) + + | { c: 1; f: number; g: string } = { +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 48, 7)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 48, 13)) +>g : Symbol(g, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 48, 24)) + + c: 0, +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 48, 40)) + + f: 10n, +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 49, 9)) + + }; + f; +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 43, 6)) + + g; +>g : Symbol(g, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 44, 6)) +} + +{ + const { c, f, f }: { c: 0; f: number } | { c: 1; f: string } = { c: 0, f: 0 }; +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 57, 9)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 57, 12)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 57, 15)) +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 57, 22)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 57, 28)) +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 57, 44)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 57, 50)) +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 57, 66)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 57, 72)) + + f; +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 57, 12)) +} + +{ + const { c, f, f: g }: { c: 0; f: number } | { c: 1; f: string } = { c: 0, f: 0 }; +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 9)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 12)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 31), Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 53)) +>g : Symbol(g, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 15)) +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 25)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 31)) +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 47)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 53)) +>c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 69)) +>f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 75)) + + g; +>g : Symbol(g, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 15)) +} + diff --git a/testdata/baselines/reference/conformance/dependentDestructuredVariablesRefereinceInDeclaration1.types b/testdata/baselines/reference/conformance/dependentDestructuredVariablesRefereinceInDeclaration1.types new file mode 100644 index 00000000000..fc6d6b8a603 --- /dev/null +++ b/testdata/baselines/reference/conformance/dependentDestructuredVariablesRefereinceInDeclaration1.types @@ -0,0 +1,205 @@ +//// [tests/cases/conformance/controlFlow/dependentDestructuredVariablesRefereinceInDeclaration1.ts] //// + +=== dependentDestructuredVariablesRefereinceInDeclaration1.ts === +// https://github.com/microsoft/TypeScript/issues/62993 + +{ + const { c, f }: string | number = { c: 0, f }; +>c : any +>f : any +>{ c: 0, f } : { c: number; f: any; } +>c : number +>0 : 0 +>f : any + + f; +>f : any +} + +{ + const { c, f }: string | number = { c: 0, f: () => f }; +>c : any +>f : any +>{ c: 0, f: () => f } : { c: number; f: () => any; } +>c : number +>0 : 0 +>f : () => any +>() => f : () => any +>f : any + + f; +>f : any +} + +{ + const { c, f, g = f }: string | number = { c: 0, f: 0, g: 0 }; +>c : any +>f : any +>g : any +>f : any +>{ c: 0, f: 0, g: 0 } : { c: number; f: number; g: number; } +>c : number +>0 : 0 +>f : number +>0 : 0 +>g : number +>0 : 0 + + f; +>f : any + + g; +>g : any +} + +{ + const { c, f, f }: string | number = { c: 0, f: 0 }; +>c : any +>f : any +>f : any +>{ c: 0, f: 0 } : { c: number; f: number; } +>c : number +>0 : 0 +>f : number +>0 : 0 + + f; +>f : any +} + +{ + const { c, f, f: g }: string | number = { c: 0, f: 0 }; +>c : any +>f : any +>f : any +>g : any +>{ c: 0, f: 0 } : { c: number; f: number; } +>c : number +>0 : 0 +>f : number +>0 : 0 + + g; +>g : any +} + +{ + const { c, f }: { c: 0; f: number } | { c: 1; f: string } = { c: 0, f }; +>c : 0 | 1 +>f : any +>c : 0 +>f : number +>c : 1 +>f : string +>{ c: 0, f } : { c: 0; f: any; } +>c : 0 +>0 : 0 +>f : any + + f; +>f : string | number +} + +{ + const { c, f }: { c: 0; f: () => unknown } | { c: 1; f: string } = { +>c : 0 | 1 +>f : string | (() => unknown) +>c : 0 +>f : () => unknown +>c : 1 +>f : string +>{ c: 0, f: () => f, } : { c: 0; f: () => string | (() => unknown); } + + c: 0, +>c : 0 +>0 : 0 + + f: () => f, +>f : () => string | (() => unknown) +>() => f : () => string | (() => unknown) +>f : string | (() => unknown) + + }; + f; +>f : () => unknown +} + +{ + const { + c, +>c : 0 | 1 + + f, +>f : number | bigint + + g = f, +>g : string | number | bigint +>f : number | bigint + + }: + | { c: 0; f: bigint; g?: bigint | number } +>c : 0 +>f : bigint +>g : number | bigint | undefined + + | { c: 1; f: number; g: string } = { +>c : 1 +>f : number +>g : string +>{ c: 0, f: 10n, } : { c: 0; f: bigint; } + + c: 0, +>c : 0 +>0 : 0 + + f: 10n, +>f : bigint +>10n : 10n + + }; + f; +>f : bigint + + g; +>g : string | number | bigint +} + +{ + const { c, f, f }: { c: 0; f: number } | { c: 1; f: string } = { c: 0, f: 0 }; +>c : 0 | 1 +>f : string | number +>f : string | number +>c : 0 +>f : number +>c : 1 +>f : string +>{ c: 0, f: 0 } : { c: 0; f: number; } +>c : 0 +>0 : 0 +>f : number +>0 : 0 + + f; +>f : number +} + +{ + const { c, f, f: g }: { c: 0; f: number } | { c: 1; f: string } = { c: 0, f: 0 }; +>c : 0 | 1 +>f : string | number +>f : any +>g : string | number +>c : 0 +>f : number +>c : 1 +>f : string +>{ c: 0, f: 0 } : { c: 0; f: number; } +>c : 0 +>0 : 0 +>f : number +>0 : 0 + + g; +>g : number +} + diff --git a/testdata/tests/cases/compiler/controlFlowDependentDestructuringOverloadedAssertion.ts b/testdata/tests/cases/compiler/controlFlowDependentDestructuringOverloadedAssertion.ts new file mode 100644 index 00000000000..e535c402ecd --- /dev/null +++ b/testdata/tests/cases/compiler/controlFlowDependentDestructuringOverloadedAssertion.ts @@ -0,0 +1,19 @@ +// @strict: true +// @noEmit: true + +// https://github.com/microsoft/typescript-go/issues/4572 + +type State = + | { status: "ready"; payload: { value?: string } } + | { status: "pending"; payload?: undefined }; + +declare function getState(): State; +declare function assert(condition: boolean): asserts condition; +declare function assert(condition: boolean, message: string): asserts condition; + +const readValue = () => { + const { status, payload } = getState(); + if (status !== "ready") throw new Error("Value is not ready."); + assert(payload.value !== undefined); + return payload.value; +}; diff --git a/testdata/tests/cases/conformance/controlFlow/dependentDestructuredVariablesNoCrash1.ts b/testdata/tests/cases/conformance/controlFlow/dependentDestructuredVariablesNoCrash1.ts new file mode 100644 index 00000000000..b11b3640740 --- /dev/null +++ b/testdata/tests/cases/conformance/controlFlow/dependentDestructuredVariablesNoCrash1.ts @@ -0,0 +1,8 @@ +// @strict: true +// @declaration: true + +// https://github.com/microsoft/TypeScript/issues/63044 + +function f() + +function f([first, undefined]?: () => any = undefined) {} diff --git a/testdata/tests/cases/conformance/controlFlow/dependentDestructuredVariablesNoCrash2.ts b/testdata/tests/cases/conformance/controlFlow/dependentDestructuredVariablesNoCrash2.ts new file mode 100644 index 00000000000..e0ed97eeb83 --- /dev/null +++ b/testdata/tests/cases/conformance/controlFlow/dependentDestructuredVariablesNoCrash2.ts @@ -0,0 +1,6 @@ +// @strict: true +// @declaration: true + +// https://github.com/microsoft/TypeScript/issues/63091 + +function ([undefined, unknown]: string | undefined = undefined) diff --git a/testdata/tests/cases/conformance/controlFlow/dependentDestructuredVariablesNoCrash3.ts b/testdata/tests/cases/conformance/controlFlow/dependentDestructuredVariablesNoCrash3.ts new file mode 100644 index 00000000000..22b223240f4 --- /dev/null +++ b/testdata/tests/cases/conformance/controlFlow/dependentDestructuredVariablesNoCrash3.ts @@ -0,0 +1,6 @@ +// @strict: true +// @declaration: true + +// https://github.com/microsoft/TypeScript/issues/63093 + +const [r0Def, r0, r1Def, as, string, r1, r2, r3Def, r3]: boolean = (test as number < string > ).ranges(); diff --git a/testdata/tests/cases/conformance/controlFlow/dependentDestructuredVariablesRefereinceInDeclaration1.ts b/testdata/tests/cases/conformance/controlFlow/dependentDestructuredVariablesRefereinceInDeclaration1.ts new file mode 100644 index 00000000000..d72cb155371 --- /dev/null +++ b/testdata/tests/cases/conformance/controlFlow/dependentDestructuredVariablesRefereinceInDeclaration1.ts @@ -0,0 +1,69 @@ +// @strict: true +// @target: esnext +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/62993 + +{ + const { c, f }: string | number = { c: 0, f }; + f; +} + +{ + const { c, f }: string | number = { c: 0, f: () => f }; + f; +} + +{ + const { c, f, g = f }: string | number = { c: 0, f: 0, g: 0 }; + f; + g; +} + +{ + const { c, f, f }: string | number = { c: 0, f: 0 }; + f; +} + +{ + const { c, f, f: g }: string | number = { c: 0, f: 0 }; + g; +} + +{ + const { c, f }: { c: 0; f: number } | { c: 1; f: string } = { c: 0, f }; + f; +} + +{ + const { c, f }: { c: 0; f: () => unknown } | { c: 1; f: string } = { + c: 0, + f: () => f, + }; + f; +} + +{ + const { + c, + f, + g = f, + }: + | { c: 0; f: bigint; g?: bigint | number } + | { c: 1; f: number; g: string } = { + c: 0, + f: 10n, + }; + f; + g; +} + +{ + const { c, f, f }: { c: 0; f: number } | { c: 1; f: string } = { c: 0, f: 0 }; + f; +} + +{ + const { c, f, f: g }: { c: 0; f: number } | { c: 1; f: string } = { c: 0, f: 0 }; + g; +} From f4cf215930c986e35d6263df9b8c9586e6fa76f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 11 Jul 2026 01:25:38 +0200 Subject: [PATCH 2/9] hybrid --- internal/checker/checker.go | 35 ++++++++++++++++++++--------------- internal/checker/types.go | 1 + 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/internal/checker/checker.go b/internal/checker/checker.go index 82db8b92c7c..9ea6d240471 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -13684,21 +13684,26 @@ func (c *Checker) getNarrowedTypeOfSymbol(symbol *ast.Symbol, location *ast.Node parent := declaration.Parent.Parent rootDeclaration := ast.GetRootDeclaration(parent) if ast.IsVariableDeclaration(rootDeclaration) && c.getCombinedNodeFlagsCached(rootDeclaration)&ast.NodeFlagsConstant != 0 || ast.IsParameterDeclaration(rootDeclaration) { - parentType := c.getTypeForBindingElementParent(parent, CheckModeNormal) - var parentTypeConstraint *Type - if parentType != nil { - parentTypeConstraint = c.mapType(parentType, c.getBaseConstraintOrType) - } - if parentTypeConstraint != nil && parentTypeConstraint.flags&TypeFlagsUnion != 0 && !(ast.IsParameterDeclaration(rootDeclaration) && c.isSomeSymbolAssigned(rootDeclaration)) { - pattern := declaration.Parent - narrowedType := c.getFlowTypeOfReferenceEx(pattern, parentTypeConstraint, parentTypeConstraint, nil /*flowContainer*/, getFlowNodeOfNode(location)) - if narrowedType.flags&TypeFlagsNever != 0 { - t = c.neverType - } else { - // Destructurings are validated against the parent type elsewhere. Here we disable tuple bounds - // checks because the narrowed type may have lower arity than the full parent type. For example, - // for the declaration [x, y]: [1, 2] | [3], we may have narrowed the parent type to just [3]. - t = c.getBindingElementTypeFromParentType(declaration, narrowedType, true /*noTupleBoundsCheck*/) + links := c.nodeLinks.Get(parent) + if links.flags&NodeCheckFlagsInCheckIdentifier == 0 { + links.flags |= NodeCheckFlagsInCheckIdentifier + parentType := c.getTypeForBindingElementParent(parent, CheckModeNormal) + var parentTypeConstraint *Type + if parentType != nil { + parentTypeConstraint = c.mapType(parentType, c.getBaseConstraintOrType) + } + links.flags &^= NodeCheckFlagsInCheckIdentifier + if parentTypeConstraint != nil && parentTypeConstraint.flags&TypeFlagsUnion != 0 && !(ast.IsParameterDeclaration(rootDeclaration) && c.isSomeSymbolAssigned(rootDeclaration)) { + pattern := declaration.Parent + narrowedType := c.getFlowTypeOfReferenceEx(pattern, parentTypeConstraint, parentTypeConstraint, nil /*flowContainer*/, getFlowNodeOfNode(location)) + if narrowedType.flags&TypeFlagsNever != 0 { + t = c.neverType + } else { + // Destructurings are validated against the parent type elsewhere. Here we disable tuple bounds + // checks because the narrowed type may have lower arity than the full parent type. For example, + // for the declaration [x, y]: [1, 2] | [3], we may have narrowed the parent type to just [3]. + t = c.getBindingElementTypeFromParentType(declaration, narrowedType, true /*noTupleBoundsCheck*/) + } } } } diff --git a/internal/checker/types.go b/internal/checker/types.go index 4d63c594b84..bd13420922e 100644 --- a/internal/checker/types.go +++ b/internal/checker/types.go @@ -352,6 +352,7 @@ const ( NodeCheckFlagsAssignmentsMarked NodeCheckFlags = 1 << 17 // Parameter assignments have been marked NodeCheckFlagsContainsClassWithPrivateIdentifiers NodeCheckFlags = 1 << 20 // Marked on all block-scoped containers containing a class with private identifiers. NodeCheckFlagsContainsSuperPropertyInStaticInitializer NodeCheckFlags = 1 << 21 // Marked on all block-scoped containers containing a static initializer with 'super.x' or 'super[x]'. + NodeCheckFlagsInCheckIdentifier NodeCheckFlags = 1 << 22 NodeCheckFlagsInitializerIsUndefined NodeCheckFlags = 1 << 24 NodeCheckFlagsInitializerIsUndefinedComputed NodeCheckFlags = 1 << 25 ) From b913a064bb504f548c8deda540e79d014ec87d09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 11 Jul 2026 12:14:33 +0200 Subject: [PATCH 3/9] fix the crossfile issue --- internal/checker/checker.go | 2 +- ...dentDestructuringCrossFilePosition.symbols | 32 +++++++++++++++++ ...endentDestructuringCrossFilePosition.types | 34 +++++++++++++++++++ ...dependentDestructuringCrossFilePosition.ts | 15 ++++++++ 4 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 testdata/baselines/reference/compiler/dependentDestructuringCrossFilePosition.symbols create mode 100644 testdata/baselines/reference/compiler/dependentDestructuringCrossFilePosition.types create mode 100644 testdata/tests/cases/compiler/dependentDestructuringCrossFilePosition.ts diff --git a/internal/checker/checker.go b/internal/checker/checker.go index 9ea6d240471..f7108917b1d 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -13655,7 +13655,7 @@ func (c *Checker) isInPropertyInitializerOrClassStaticBlock(node *ast.Node, igno func (c *Checker) getNarrowedTypeOfSymbol(symbol *ast.Symbol, location *ast.Node) *Type { t := c.getTypeOfSymbol(symbol) declaration := symbol.ValueDeclaration - if declaration != nil && !ast.GetRootDeclaration(declaration).Loc.ContainsInclusive(location.Pos()) { + if declaration != nil && (!ast.GetRootDeclaration(declaration).Loc.ContainsInclusive(location.Pos()) || ast.GetSourceFileOfNode(declaration) != ast.GetSourceFileOfNode(location)) { switch { // If we have a non-rest binding element with no initializer declared as a const variable or a const-like // parameter (a parameter for which there are no assignments in the function body), and if the parent type diff --git a/testdata/baselines/reference/compiler/dependentDestructuringCrossFilePosition.symbols b/testdata/baselines/reference/compiler/dependentDestructuringCrossFilePosition.symbols new file mode 100644 index 00000000000..2bb96f01885 --- /dev/null +++ b/testdata/baselines/reference/compiler/dependentDestructuringCrossFilePosition.symbols @@ -0,0 +1,32 @@ +//// [tests/cases/compiler/dependentDestructuringCrossFilePosition.ts] //// + +=== types.d.ts === +type U = +>U : Symbol(U, Decl(types.d.ts, 0, 0)) + + | { kind: "a"; payload: number } +>kind : Symbol(kind, Decl(types.d.ts, 1, 7)) +>payload : Symbol(payload, Decl(types.d.ts, 1, 18)) + + | { kind: "b"; payload: string }; +>kind : Symbol(kind, Decl(types.d.ts, 2, 7)) +>payload : Symbol(payload, Decl(types.d.ts, 2, 18)) + +declare function make(): U; +>make : Symbol(make, Decl(types.d.ts, 2, 37)) +>U : Symbol(U, Decl(types.d.ts, 0, 0)) + +=== a.ts === +const { kind, payload }: U = make(); +>kind : Symbol(kind, Decl(a.ts, 0, 7)) +>payload : Symbol(payload, Decl(a.ts, 0, 13)) +>U : Symbol(U, Decl(types.d.ts, 0, 0)) +>make : Symbol(make, Decl(types.d.ts, 2, 37)) + +=== b.ts === +if (kind === "a") payload.toFixed(); +>kind : Symbol(kind, Decl(a.ts, 0, 7)) +>payload.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>payload : Symbol(payload, Decl(a.ts, 0, 13)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) + diff --git a/testdata/baselines/reference/compiler/dependentDestructuringCrossFilePosition.types b/testdata/baselines/reference/compiler/dependentDestructuringCrossFilePosition.types new file mode 100644 index 00000000000..a9cf06789cf --- /dev/null +++ b/testdata/baselines/reference/compiler/dependentDestructuringCrossFilePosition.types @@ -0,0 +1,34 @@ +//// [tests/cases/compiler/dependentDestructuringCrossFilePosition.ts] //// + +=== types.d.ts === +type U = +>U : U + + | { kind: "a"; payload: number } +>kind : "a" +>payload : number + + | { kind: "b"; payload: string }; +>kind : "b" +>payload : string + +declare function make(): U; +>make : () => U + +=== a.ts === +const { kind, payload }: U = make(); +>kind : "a" | "b" +>payload : string | number +>make() : U +>make : () => U + +=== b.ts === +if (kind === "a") payload.toFixed(); +>kind === "a" : boolean +>kind : "a" | "b" +>"a" : "a" +>payload.toFixed() : string +>payload.toFixed : (fractionDigits?: number) => string +>payload : number +>toFixed : (fractionDigits?: number) => string + diff --git a/testdata/tests/cases/compiler/dependentDestructuringCrossFilePosition.ts b/testdata/tests/cases/compiler/dependentDestructuringCrossFilePosition.ts new file mode 100644 index 00000000000..1199255c75d --- /dev/null +++ b/testdata/tests/cases/compiler/dependentDestructuringCrossFilePosition.ts @@ -0,0 +1,15 @@ +// @strict: true +// @noEmit: true + +// @filename: types.d.ts +type U = + | { kind: "a"; payload: number } + | { kind: "b"; payload: string }; + +declare function make(): U; + +// @filename: a.ts +const { kind, payload }: U = make(); + +// @filename: b.ts +if (kind === "a") payload.toFixed(); From 88a82ff61775285d324e3bdf91b90a18d61a06d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 11 Jul 2026 14:47:21 +0200 Subject: [PATCH 4/9] fix deferred case --- internal/checker/checker.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/internal/checker/checker.go b/internal/checker/checker.go index f7108917b1d..3812ab31b38 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -13655,7 +13655,9 @@ func (c *Checker) isInPropertyInitializerOrClassStaticBlock(node *ast.Node, igno func (c *Checker) getNarrowedTypeOfSymbol(symbol *ast.Symbol, location *ast.Node) *Type { t := c.getTypeOfSymbol(symbol) declaration := symbol.ValueDeclaration - if declaration != nil && (!ast.GetRootDeclaration(declaration).Loc.ContainsInclusive(location.Pos()) || ast.GetSourceFileOfNode(declaration) != ast.GetSourceFileOfNode(location)) { + if declaration != nil && (!ast.GetRootDeclaration(declaration).Loc.ContainsInclusive(location.Pos()) || + ast.GetSourceFileOfNode(declaration) != ast.GetSourceFileOfNode(location) || + c.getControlFlowContainer(declaration) != c.getControlFlowContainer(location)) { switch { // If we have a non-rest binding element with no initializer declared as a const variable or a const-like // parameter (a parameter for which there are no assignments in the function body), and if the parent type From ca9b0db74174dfc91eb11e66e7eaf4c9f5cf5eff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 11 Jul 2026 17:37:03 +0200 Subject: [PATCH 5/9] fix extra thing --- internal/checker/checker.go | 3 +- ...ructuringBindingElementInitializer.symbols | 62 ++++++++++++++++ ...structuringBindingElementInitializer.types | 70 +++++++++++++++++++ ...ndentDestructuringDeferredCallback.symbols | 40 +++++++++++ ...pendentDestructuringDeferredCallback.types | 46 ++++++++++++ ...tDestructuringBindingElementInitializer.ts | 20 ++++++ .../dependentDestructuringDeferredCallback.ts | 14 ++++ 7 files changed, 254 insertions(+), 1 deletion(-) create mode 100644 testdata/baselines/reference/compiler/dependentDestructuringBindingElementInitializer.symbols create mode 100644 testdata/baselines/reference/compiler/dependentDestructuringBindingElementInitializer.types create mode 100644 testdata/baselines/reference/compiler/dependentDestructuringDeferredCallback.symbols create mode 100644 testdata/baselines/reference/compiler/dependentDestructuringDeferredCallback.types create mode 100644 testdata/tests/cases/compiler/dependentDestructuringBindingElementInitializer.ts create mode 100644 testdata/tests/cases/compiler/dependentDestructuringDeferredCallback.ts diff --git a/internal/checker/checker.go b/internal/checker/checker.go index 3812ab31b38..de303d31646 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -13657,7 +13657,8 @@ func (c *Checker) getNarrowedTypeOfSymbol(symbol *ast.Symbol, location *ast.Node declaration := symbol.ValueDeclaration if declaration != nil && (!ast.GetRootDeclaration(declaration).Loc.ContainsInclusive(location.Pos()) || ast.GetSourceFileOfNode(declaration) != ast.GetSourceFileOfNode(location) || - c.getControlFlowContainer(declaration) != c.getControlFlowContainer(location)) { + c.getControlFlowContainer(declaration) != c.getControlFlowContainer(location) || + c.isSameScopedBindingElement(location, declaration)) { switch { // If we have a non-rest binding element with no initializer declared as a const variable or a const-like // parameter (a parameter for which there are no assignments in the function body), and if the parent type diff --git a/testdata/baselines/reference/compiler/dependentDestructuringBindingElementInitializer.symbols b/testdata/baselines/reference/compiler/dependentDestructuringBindingElementInitializer.symbols new file mode 100644 index 00000000000..0aaf3801134 --- /dev/null +++ b/testdata/baselines/reference/compiler/dependentDestructuringBindingElementInitializer.symbols @@ -0,0 +1,62 @@ +//// [tests/cases/compiler/dependentDestructuringBindingElementInitializer.ts] //// + +=== dependentDestructuringBindingElementInitializer.ts === +type U = +>U : Symbol(U, Decl(dependentDestructuringBindingElementInitializer.ts, 0, 0)) + + | { kind: "a"; payload: number; extra?: unknown } +>kind : Symbol(kind, Decl(dependentDestructuringBindingElementInitializer.ts, 1, 7)) +>payload : Symbol(payload, Decl(dependentDestructuringBindingElementInitializer.ts, 1, 18)) +>extra : Symbol(extra, Decl(dependentDestructuringBindingElementInitializer.ts, 1, 35)) + + | { kind: "b"; payload: string; extra?: unknown }; +>kind : Symbol(kind, Decl(dependentDestructuringBindingElementInitializer.ts, 2, 7)) +>payload : Symbol(payload, Decl(dependentDestructuringBindingElementInitializer.ts, 2, 18)) +>extra : Symbol(extra, Decl(dependentDestructuringBindingElementInitializer.ts, 2, 35)) + +declare const u: U; +>u : Symbol(u, Decl(dependentDestructuringBindingElementInitializer.ts, 4, 13)) +>U : Symbol(U, Decl(dependentDestructuringBindingElementInitializer.ts, 0, 0)) + +const { + kind, +>kind : Symbol(kind, Decl(dependentDestructuringBindingElementInitializer.ts, 6, 7)) + + payload, +>payload : Symbol(payload, Decl(dependentDestructuringBindingElementInitializer.ts, 7, 9)) + + extra = kind === "a" ? payload.toFixed() : payload.toUpperCase(), +>extra : Symbol(extra, Decl(dependentDestructuringBindingElementInitializer.ts, 8, 12)) +>kind : Symbol(kind, Decl(dependentDestructuringBindingElementInitializer.ts, 6, 7)) +>payload.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>payload : Symbol(payload, Decl(dependentDestructuringBindingElementInitializer.ts, 7, 9)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>payload.toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --)) +>payload : Symbol(payload, Decl(dependentDestructuringBindingElementInitializer.ts, 7, 9)) +>toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --)) + +} = u; +>u : Symbol(u, Decl(dependentDestructuringBindingElementInitializer.ts, 4, 13)) + +function f({ +>f : Symbol(f, Decl(dependentDestructuringBindingElementInitializer.ts, 10, 6)) + + kind, +>kind : Symbol(kind, Decl(dependentDestructuringBindingElementInitializer.ts, 12, 12)) + + payload, +>payload : Symbol(payload, Decl(dependentDestructuringBindingElementInitializer.ts, 13, 9)) + + extra = kind === "a" ? payload.toFixed() : payload.toUpperCase(), +>extra : Symbol(extra, Decl(dependentDestructuringBindingElementInitializer.ts, 14, 12)) +>kind : Symbol(kind, Decl(dependentDestructuringBindingElementInitializer.ts, 12, 12)) +>payload.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>payload : Symbol(payload, Decl(dependentDestructuringBindingElementInitializer.ts, 13, 9)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>payload.toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --)) +>payload : Symbol(payload, Decl(dependentDestructuringBindingElementInitializer.ts, 13, 9)) +>toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --)) + +}: U) {} +>U : Symbol(U, Decl(dependentDestructuringBindingElementInitializer.ts, 0, 0)) + diff --git a/testdata/baselines/reference/compiler/dependentDestructuringBindingElementInitializer.types b/testdata/baselines/reference/compiler/dependentDestructuringBindingElementInitializer.types new file mode 100644 index 00000000000..0dcd3d8a64c --- /dev/null +++ b/testdata/baselines/reference/compiler/dependentDestructuringBindingElementInitializer.types @@ -0,0 +1,70 @@ +//// [tests/cases/compiler/dependentDestructuringBindingElementInitializer.ts] //// + +=== dependentDestructuringBindingElementInitializer.ts === +type U = +>U : U + + | { kind: "a"; payload: number; extra?: unknown } +>kind : "a" +>payload : number +>extra : unknown + + | { kind: "b"; payload: string; extra?: unknown }; +>kind : "b" +>payload : string +>extra : unknown + +declare const u: U; +>u : U + +const { + kind, +>kind : "a" | "b" + + payload, +>payload : string | number + + extra = kind === "a" ? payload.toFixed() : payload.toUpperCase(), +>extra : unknown +>kind === "a" ? payload.toFixed() : payload.toUpperCase() : string +>kind === "a" : boolean +>kind : "a" | "b" +>"a" : "a" +>payload.toFixed() : string +>payload.toFixed : (fractionDigits?: number) => string +>payload : number +>toFixed : (fractionDigits?: number) => string +>payload.toUpperCase() : string +>payload.toUpperCase : () => string +>payload : string +>toUpperCase : () => string + +} = u; +>u : U + +function f({ +>f : ({ kind, payload, extra, }: U) => void + + kind, +>kind : "a" | "b" + + payload, +>payload : string | number + + extra = kind === "a" ? payload.toFixed() : payload.toUpperCase(), +>extra : unknown +>kind === "a" ? payload.toFixed() : payload.toUpperCase() : string +>kind === "a" : boolean +>kind : "a" | "b" +>"a" : "a" +>payload.toFixed() : string +>payload.toFixed : (fractionDigits?: number) => string +>payload : number +>toFixed : (fractionDigits?: number) => string +>payload.toUpperCase() : string +>payload.toUpperCase : () => string +>payload : string +>toUpperCase : () => string + +}: U) {} + diff --git a/testdata/baselines/reference/compiler/dependentDestructuringDeferredCallback.symbols b/testdata/baselines/reference/compiler/dependentDestructuringDeferredCallback.symbols new file mode 100644 index 00000000000..5e6e3f2fda9 --- /dev/null +++ b/testdata/baselines/reference/compiler/dependentDestructuringDeferredCallback.symbols @@ -0,0 +1,40 @@ +//// [tests/cases/compiler/dependentDestructuringDeferredCallback.ts] //// + +=== dependentDestructuringDeferredCallback.ts === +type U = +>U : Symbol(U, Decl(dependentDestructuringDeferredCallback.ts, 0, 0)) + + | { kind: "a"; payload: number; callback: () => void } +>kind : Symbol(kind, Decl(dependentDestructuringDeferredCallback.ts, 1, 7)) +>payload : Symbol(payload, Decl(dependentDestructuringDeferredCallback.ts, 1, 18)) +>callback : Symbol(callback, Decl(dependentDestructuringDeferredCallback.ts, 1, 35)) + + | { kind: "b"; payload: string; callback: () => void }; +>kind : Symbol(kind, Decl(dependentDestructuringDeferredCallback.ts, 2, 7)) +>payload : Symbol(payload, Decl(dependentDestructuringDeferredCallback.ts, 2, 18)) +>callback : Symbol(callback, Decl(dependentDestructuringDeferredCallback.ts, 2, 35)) + +const { kind, payload, callback }: U = { +>kind : Symbol(kind, Decl(dependentDestructuringDeferredCallback.ts, 4, 7)) +>payload : Symbol(payload, Decl(dependentDestructuringDeferredCallback.ts, 4, 13)) +>callback : Symbol(callback, Decl(dependentDestructuringDeferredCallback.ts, 4, 22)) +>U : Symbol(U, Decl(dependentDestructuringDeferredCallback.ts, 0, 0)) + + kind: "a", +>kind : Symbol(kind, Decl(dependentDestructuringDeferredCallback.ts, 4, 40)) + + payload: 1, +>payload : Symbol(payload, Decl(dependentDestructuringDeferredCallback.ts, 5, 14)) + + callback: () => { +>callback : Symbol(callback, Decl(dependentDestructuringDeferredCallback.ts, 6, 15)) + + if (kind === "a") payload.toFixed(); +>kind : Symbol(kind, Decl(dependentDestructuringDeferredCallback.ts, 4, 7)) +>payload.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>payload : Symbol(payload, Decl(dependentDestructuringDeferredCallback.ts, 4, 13)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) + + }, +}; + diff --git a/testdata/baselines/reference/compiler/dependentDestructuringDeferredCallback.types b/testdata/baselines/reference/compiler/dependentDestructuringDeferredCallback.types new file mode 100644 index 00000000000..363d9627521 --- /dev/null +++ b/testdata/baselines/reference/compiler/dependentDestructuringDeferredCallback.types @@ -0,0 +1,46 @@ +//// [tests/cases/compiler/dependentDestructuringDeferredCallback.ts] //// + +=== dependentDestructuringDeferredCallback.ts === +type U = +>U : U + + | { kind: "a"; payload: number; callback: () => void } +>kind : "a" +>payload : number +>callback : () => void + + | { kind: "b"; payload: string; callback: () => void }; +>kind : "b" +>payload : string +>callback : () => void + +const { kind, payload, callback }: U = { +>kind : "a" | "b" +>payload : string | number +>callback : (() => void) | (() => void) +>{ kind: "a", payload: 1, callback: () => { if (kind === "a") payload.toFixed(); },} : { kind: "a"; payload: number; callback: () => void; } + + kind: "a", +>kind : "a" +>"a" : "a" + + payload: 1, +>payload : number +>1 : 1 + + callback: () => { +>callback : () => void +>() => { if (kind === "a") payload.toFixed(); } : () => void + + if (kind === "a") payload.toFixed(); +>kind === "a" : boolean +>kind : "a" | "b" +>"a" : "a" +>payload.toFixed() : string +>payload.toFixed : (fractionDigits?: number) => string +>payload : number +>toFixed : (fractionDigits?: number) => string + + }, +}; + diff --git a/testdata/tests/cases/compiler/dependentDestructuringBindingElementInitializer.ts b/testdata/tests/cases/compiler/dependentDestructuringBindingElementInitializer.ts new file mode 100644 index 00000000000..7006dffe572 --- /dev/null +++ b/testdata/tests/cases/compiler/dependentDestructuringBindingElementInitializer.ts @@ -0,0 +1,20 @@ +// @strict: true +// @noEmit: true + +type U = + | { kind: "a"; payload: number; extra?: unknown } + | { kind: "b"; payload: string; extra?: unknown }; + +declare const u: U; + +const { + kind, + payload, + extra = kind === "a" ? payload.toFixed() : payload.toUpperCase(), +} = u; + +function f({ + kind, + payload, + extra = kind === "a" ? payload.toFixed() : payload.toUpperCase(), +}: U) {} diff --git a/testdata/tests/cases/compiler/dependentDestructuringDeferredCallback.ts b/testdata/tests/cases/compiler/dependentDestructuringDeferredCallback.ts new file mode 100644 index 00000000000..6a8ebbbd6f6 --- /dev/null +++ b/testdata/tests/cases/compiler/dependentDestructuringDeferredCallback.ts @@ -0,0 +1,14 @@ +// @strict: true +// @noEmit: true + +type U = + | { kind: "a"; payload: number; callback: () => void } + | { kind: "b"; payload: string; callback: () => void }; + +const { kind, payload, callback }: U = { + kind: "a", + payload: 1, + callback: () => { + if (kind === "a") payload.toFixed(); + }, +}; From 611f9ea92be6c5b75940d21392abc7d69e191344 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 11 Jul 2026 18:09:30 +0200 Subject: [PATCH 6/9] simplify --- internal/checker/checker.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/internal/checker/checker.go b/internal/checker/checker.go index de303d31646..69be631355d 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -13655,10 +13655,7 @@ func (c *Checker) isInPropertyInitializerOrClassStaticBlock(node *ast.Node, igno func (c *Checker) getNarrowedTypeOfSymbol(symbol *ast.Symbol, location *ast.Node) *Type { t := c.getTypeOfSymbol(symbol) declaration := symbol.ValueDeclaration - if declaration != nil && (!ast.GetRootDeclaration(declaration).Loc.ContainsInclusive(location.Pos()) || - ast.GetSourceFileOfNode(declaration) != ast.GetSourceFileOfNode(location) || - c.getControlFlowContainer(declaration) != c.getControlFlowContainer(location) || - c.isSameScopedBindingElement(location, declaration)) { + if declaration != nil { switch { // If we have a non-rest binding element with no initializer declared as a const variable or a const-like // parameter (a parameter for which there are no assignments in the function body), and if the parent type @@ -13684,8 +13681,15 @@ func (c *Checker) getNarrowedTypeOfSymbol(symbol *ast.Symbol, location *ast.Node // as if it occurred in the specified location. We then recompute the narrowed binding element type by // destructuring from the narrowed parent type. case ast.IsBindingElement(declaration) && declaration.Initializer() == nil && !hasDotDotDotToken(declaration) && len(declaration.Parent.Elements()) >= 2: + rootDeclaration := ast.GetRootDeclaration(declaration) + rootInitializer := rootDeclaration.Initializer() + // Avoid declaration circularity without blocking binding defaults or nested callbacks. + if rootInitializer != nil && + ast.IsNodeDescendantOf(location, rootInitializer) && + c.getControlFlowContainer(declaration) == c.getControlFlowContainer(location) { + break + } parent := declaration.Parent.Parent - rootDeclaration := ast.GetRootDeclaration(parent) if ast.IsVariableDeclaration(rootDeclaration) && c.getCombinedNodeFlagsCached(rootDeclaration)&ast.NodeFlagsConstant != 0 || ast.IsParameterDeclaration(rootDeclaration) { links := c.nodeLinks.Get(parent) if links.flags&NodeCheckFlagsInCheckIdentifier == 0 { From ef941faeece414459c18ac0fdb207fcecdcde8a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 11 Jul 2026 18:13:59 +0200 Subject: [PATCH 7/9] add comment --- internal/checker/checker.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/checker/checker.go b/internal/checker/checker.go index 69be631355d..febfda631a3 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -13699,6 +13699,7 @@ func (c *Checker) getNarrowedTypeOfSymbol(symbol *ast.Symbol, location *ast.Node if parentType != nil { parentTypeConstraint = c.mapType(parentType, c.getBaseConstraintOrType) } + // Guard parent-type resolution only; flow analysis should allow re-entrant narrowing links.flags &^= NodeCheckFlagsInCheckIdentifier if parentTypeConstraint != nil && parentTypeConstraint.flags&TypeFlagsUnion != 0 && !(ast.IsParameterDeclaration(rootDeclaration) && c.isSomeSymbolAssigned(rootDeclaration)) { pattern := declaration.Parent From 24fda956e715a6d87fe8fb8a3dd627401c87ca07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 13 Jul 2026 15:06:09 +0200 Subject: [PATCH 8/9] add test --- ...ustiveSwitchTupleLengthFallthrough.symbols | 39 ++++ ...haustiveSwitchTupleLengthFallthrough.types | 45 +++++ ...dVariablesRefereinceInDeclaration1.symbols | 175 ------------------ ...riablesReferenceInDeclaration1.errors.txt} | 58 +++--- ...edVariablesReferenceInDeclaration1.symbols | 175 ++++++++++++++++++ ...redVariablesReferenceInDeclaration1.types} | 4 +- .../exhaustiveSwitchTupleLengthFallthrough.ts | 20 ++ ...cturedVariablesReferenceInDeclaration1.ts} | 0 8 files changed, 310 insertions(+), 206 deletions(-) create mode 100644 testdata/baselines/reference/compiler/exhaustiveSwitchTupleLengthFallthrough.symbols create mode 100644 testdata/baselines/reference/compiler/exhaustiveSwitchTupleLengthFallthrough.types delete mode 100644 testdata/baselines/reference/conformance/dependentDestructuredVariablesRefereinceInDeclaration1.symbols rename testdata/baselines/reference/conformance/{dependentDestructuredVariablesRefereinceInDeclaration1.errors.txt => dependentDestructuredVariablesReferenceInDeclaration1.errors.txt} (54%) create mode 100644 testdata/baselines/reference/conformance/dependentDestructuredVariablesReferenceInDeclaration1.symbols rename testdata/baselines/reference/conformance/{dependentDestructuredVariablesRefereinceInDeclaration1.types => dependentDestructuredVariablesReferenceInDeclaration1.types} (89%) create mode 100644 testdata/tests/cases/compiler/exhaustiveSwitchTupleLengthFallthrough.ts rename testdata/tests/cases/conformance/controlFlow/{dependentDestructuredVariablesRefereinceInDeclaration1.ts => dependentDestructuredVariablesReferenceInDeclaration1.ts} (100%) diff --git a/testdata/baselines/reference/compiler/exhaustiveSwitchTupleLengthFallthrough.symbols b/testdata/baselines/reference/compiler/exhaustiveSwitchTupleLengthFallthrough.symbols new file mode 100644 index 00000000000..1c30f0b5a60 --- /dev/null +++ b/testdata/baselines/reference/compiler/exhaustiveSwitchTupleLengthFallthrough.symbols @@ -0,0 +1,39 @@ +//// [tests/cases/compiler/exhaustiveSwitchTupleLengthFallthrough.ts] //// + +=== exhaustiveSwitchTupleLengthFallthrough.ts === +type F = +>F : Symbol(F, Decl(exhaustiveSwitchTupleLengthFallthrough.ts, 0, 0)) + + | readonly [0, readonly [number]] + | readonly [0 | 1, readonly [number, number]] + | readonly [1, readonly [number, number, number]]; + +const f = ([i, x]: F): undefined => { +>f : Symbol(f, Decl(exhaustiveSwitchTupleLengthFallthrough.ts, 5, 5)) +>i : Symbol(i, Decl(exhaustiveSwitchTupleLengthFallthrough.ts, 5, 12)) +>x : Symbol(x, Decl(exhaustiveSwitchTupleLengthFallthrough.ts, 5, 14)) +>F : Symbol(F, Decl(exhaustiveSwitchTupleLengthFallthrough.ts, 0, 0)) + + switch (i) { +>i : Symbol(i, Decl(exhaustiveSwitchTupleLengthFallthrough.ts, 5, 12)) + + case 0: { + switch (x.length) { +>x.length : Symbol(length) +>x : Symbol(x, Decl(exhaustiveSwitchTupleLengthFallthrough.ts, 5, 14)) +>length : Symbol(length) + + case 1: case 2: return undefined; +>undefined : Symbol(undefined) + } + } + case 1: { + const _: 2 | 3 = x.length; +>_ : Symbol(_, Decl(exhaustiveSwitchTupleLengthFallthrough.ts, 13, 17)) +>x.length : Symbol(length) +>x : Symbol(x, Decl(exhaustiveSwitchTupleLengthFallthrough.ts, 5, 14)) +>length : Symbol(length) + } + } +}; + diff --git a/testdata/baselines/reference/compiler/exhaustiveSwitchTupleLengthFallthrough.types b/testdata/baselines/reference/compiler/exhaustiveSwitchTupleLengthFallthrough.types new file mode 100644 index 00000000000..13ac7e8dcf2 --- /dev/null +++ b/testdata/baselines/reference/compiler/exhaustiveSwitchTupleLengthFallthrough.types @@ -0,0 +1,45 @@ +//// [tests/cases/compiler/exhaustiveSwitchTupleLengthFallthrough.ts] //// + +=== exhaustiveSwitchTupleLengthFallthrough.ts === +type F = +>F : F + + | readonly [0, readonly [number]] + | readonly [0 | 1, readonly [number, number]] + | readonly [1, readonly [number, number, number]]; + +const f = ([i, x]: F): undefined => { +>f : ([i, x]: F) => undefined +>([i, x]: F): undefined => { switch (i) { case 0: { switch (x.length) { case 1: case 2: return undefined; } } case 1: { const _: 2 | 3 = x.length; } }} : ([i, x]: F) => undefined +>i : 0 | 1 +>x : readonly [number] | readonly [number, number] | readonly [number, number, number] + + switch (i) { +>i : 0 | 1 + + case 0: { +>0 : 0 + + switch (x.length) { +>x.length : 1 | 2 +>x : readonly [number] | readonly [number, number] +>length : 1 | 2 + + case 1: case 2: return undefined; +>1 : 1 +>2 : 2 +>undefined : undefined + } + } + case 1: { +>1 : 1 + + const _: 2 | 3 = x.length; +>_ : 2 | 3 +>x.length : 2 | 3 +>x : readonly [number, number] | readonly [number, number, number] +>length : 2 | 3 + } + } +}; + diff --git a/testdata/baselines/reference/conformance/dependentDestructuredVariablesRefereinceInDeclaration1.symbols b/testdata/baselines/reference/conformance/dependentDestructuredVariablesRefereinceInDeclaration1.symbols deleted file mode 100644 index b370d5ccbb6..00000000000 --- a/testdata/baselines/reference/conformance/dependentDestructuredVariablesRefereinceInDeclaration1.symbols +++ /dev/null @@ -1,175 +0,0 @@ -//// [tests/cases/conformance/controlFlow/dependentDestructuredVariablesRefereinceInDeclaration1.ts] //// - -=== dependentDestructuredVariablesRefereinceInDeclaration1.ts === -// https://github.com/microsoft/TypeScript/issues/62993 - -{ - const { c, f }: string | number = { c: 0, f }; ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 3, 9)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 3, 12)) ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 3, 37)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 3, 43)) - - f; ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 3, 12)) -} - -{ - const { c, f }: string | number = { c: 0, f: () => f }; ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 8, 9)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 8, 12)) ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 8, 37)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 8, 43)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 8, 12)) - - f; ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 8, 12)) -} - -{ - const { c, f, g = f }: string | number = { c: 0, f: 0, g: 0 }; ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 13, 9)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 13, 12)) ->g : Symbol(g, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 13, 15)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 13, 12)) ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 13, 44)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 13, 50)) ->g : Symbol(g, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 13, 56)) - - f; ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 13, 12)) - - g; ->g : Symbol(g, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 13, 15)) -} - -{ - const { c, f, f }: string | number = { c: 0, f: 0 }; ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 19, 9)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 19, 12)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 19, 15)) ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 19, 40)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 19, 46)) - - f; ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 19, 12)) -} - -{ - const { c, f, f: g }: string | number = { c: 0, f: 0 }; ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 24, 9)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 24, 12)) ->g : Symbol(g, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 24, 15)) ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 24, 43)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 24, 49)) - - g; ->g : Symbol(g, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 24, 15)) -} - -{ - const { c, f }: { c: 0; f: number } | { c: 1; f: string } = { c: 0, f }; ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 29, 9)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 29, 12)) ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 29, 19)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 29, 25)) ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 29, 41)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 29, 47)) ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 29, 63)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 29, 69)) - - f; ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 29, 12)) -} - -{ - const { c, f }: { c: 0; f: () => unknown } | { c: 1; f: string } = { ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 34, 9)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 34, 12)) ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 34, 19)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 34, 25)) ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 34, 48)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 34, 54)) - - c: 0, ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 34, 70)) - - f: () => f, ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 35, 9)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 34, 12)) - - }; - f; ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 34, 12)) -} - -{ - const { - c, ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 42, 9)) - - f, ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 43, 6)) - - g = f, ->g : Symbol(g, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 44, 6)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 43, 6)) - - }: - | { c: 0; f: bigint; g?: bigint | number } ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 47, 7)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 47, 13)) ->g : Symbol(g, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 47, 24)) - - | { c: 1; f: number; g: string } = { ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 48, 7)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 48, 13)) ->g : Symbol(g, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 48, 24)) - - c: 0, ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 48, 40)) - - f: 10n, ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 49, 9)) - - }; - f; ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 43, 6)) - - g; ->g : Symbol(g, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 44, 6)) -} - -{ - const { c, f, f }: { c: 0; f: number } | { c: 1; f: string } = { c: 0, f: 0 }; ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 57, 9)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 57, 12)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 57, 15)) ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 57, 22)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 57, 28)) ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 57, 44)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 57, 50)) ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 57, 66)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 57, 72)) - - f; ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 57, 12)) -} - -{ - const { c, f, f: g }: { c: 0; f: number } | { c: 1; f: string } = { c: 0, f: 0 }; ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 9)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 12)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 31), Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 53)) ->g : Symbol(g, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 15)) ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 25)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 31)) ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 47)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 53)) ->c : Symbol(c, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 69)) ->f : Symbol(f, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 75)) - - g; ->g : Symbol(g, Decl(dependentDestructuredVariablesRefereinceInDeclaration1.ts, 62, 15)) -} - diff --git a/testdata/baselines/reference/conformance/dependentDestructuredVariablesRefereinceInDeclaration1.errors.txt b/testdata/baselines/reference/conformance/dependentDestructuredVariablesReferenceInDeclaration1.errors.txt similarity index 54% rename from testdata/baselines/reference/conformance/dependentDestructuredVariablesRefereinceInDeclaration1.errors.txt rename to testdata/baselines/reference/conformance/dependentDestructuredVariablesReferenceInDeclaration1.errors.txt index f38d9d18394..5529a3e5e68 100644 --- a/testdata/baselines/reference/conformance/dependentDestructuredVariablesRefereinceInDeclaration1.errors.txt +++ b/testdata/baselines/reference/conformance/dependentDestructuredVariablesReferenceInDeclaration1.errors.txt @@ -1,32 +1,32 @@ -dependentDestructuredVariablesRefereinceInDeclaration1.ts(4,9): error TS2322: Type '{ c: number; f: any; }' is not assignable to type 'string | number'. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(4,11): error TS2339: Property 'c' does not exist on type 'string | number'. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(4,14): error TS2339: Property 'f' does not exist on type 'string | number'. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(4,14): error TS7022: 'f' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(4,45): error TS2448: Block-scoped variable 'f' used before its declaration. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(9,9): error TS2322: Type '{ c: number; f: () => any; }' is not assignable to type 'string | number'. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(9,11): error TS2339: Property 'c' does not exist on type 'string | number'. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(9,14): error TS2339: Property 'f' does not exist on type 'string | number'. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(14,9): error TS2322: Type '{ c: number; f: number; g: number; }' is not assignable to type 'string | number'. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(14,11): error TS2339: Property 'c' does not exist on type 'string | number'. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(14,14): error TS2339: Property 'f' does not exist on type 'string | number'. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(14,17): error TS2339: Property 'g' does not exist on type 'string | number'. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(20,9): error TS2322: Type '{ c: number; f: number; }' is not assignable to type 'string | number'. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(20,11): error TS2339: Property 'c' does not exist on type 'string | number'. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(20,14): error TS2339: Property 'f' does not exist on type 'string | number'. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(20,14): error TS2451: Cannot redeclare block-scoped variable 'f'. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(20,17): error TS2339: Property 'f' does not exist on type 'string | number'. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(20,17): error TS2451: Cannot redeclare block-scoped variable 'f'. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(25,9): error TS2322: Type '{ c: number; f: number; }' is not assignable to type 'string | number'. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(25,11): error TS2339: Property 'c' does not exist on type 'string | number'. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(25,14): error TS2339: Property 'f' does not exist on type 'string | number'. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(25,17): error TS2339: Property 'f' does not exist on type 'string | number'. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(30,14): error TS7022: 'f' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(30,71): error TS2448: Block-scoped variable 'f' used before its declaration. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(58,14): error TS2451: Cannot redeclare block-scoped variable 'f'. -dependentDestructuredVariablesRefereinceInDeclaration1.ts(58,17): error TS2451: Cannot redeclare block-scoped variable 'f'. +dependentDestructuredVariablesReferenceInDeclaration1.ts(4,9): error TS2322: Type '{ c: number; f: any; }' is not assignable to type 'string | number'. +dependentDestructuredVariablesReferenceInDeclaration1.ts(4,11): error TS2339: Property 'c' does not exist on type 'string | number'. +dependentDestructuredVariablesReferenceInDeclaration1.ts(4,14): error TS2339: Property 'f' does not exist on type 'string | number'. +dependentDestructuredVariablesReferenceInDeclaration1.ts(4,14): error TS7022: 'f' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. +dependentDestructuredVariablesReferenceInDeclaration1.ts(4,45): error TS2448: Block-scoped variable 'f' used before its declaration. +dependentDestructuredVariablesReferenceInDeclaration1.ts(9,9): error TS2322: Type '{ c: number; f: () => any; }' is not assignable to type 'string | number'. +dependentDestructuredVariablesReferenceInDeclaration1.ts(9,11): error TS2339: Property 'c' does not exist on type 'string | number'. +dependentDestructuredVariablesReferenceInDeclaration1.ts(9,14): error TS2339: Property 'f' does not exist on type 'string | number'. +dependentDestructuredVariablesReferenceInDeclaration1.ts(14,9): error TS2322: Type '{ c: number; f: number; g: number; }' is not assignable to type 'string | number'. +dependentDestructuredVariablesReferenceInDeclaration1.ts(14,11): error TS2339: Property 'c' does not exist on type 'string | number'. +dependentDestructuredVariablesReferenceInDeclaration1.ts(14,14): error TS2339: Property 'f' does not exist on type 'string | number'. +dependentDestructuredVariablesReferenceInDeclaration1.ts(14,17): error TS2339: Property 'g' does not exist on type 'string | number'. +dependentDestructuredVariablesReferenceInDeclaration1.ts(20,9): error TS2322: Type '{ c: number; f: number; }' is not assignable to type 'string | number'. +dependentDestructuredVariablesReferenceInDeclaration1.ts(20,11): error TS2339: Property 'c' does not exist on type 'string | number'. +dependentDestructuredVariablesReferenceInDeclaration1.ts(20,14): error TS2339: Property 'f' does not exist on type 'string | number'. +dependentDestructuredVariablesReferenceInDeclaration1.ts(20,14): error TS2451: Cannot redeclare block-scoped variable 'f'. +dependentDestructuredVariablesReferenceInDeclaration1.ts(20,17): error TS2339: Property 'f' does not exist on type 'string | number'. +dependentDestructuredVariablesReferenceInDeclaration1.ts(20,17): error TS2451: Cannot redeclare block-scoped variable 'f'. +dependentDestructuredVariablesReferenceInDeclaration1.ts(25,9): error TS2322: Type '{ c: number; f: number; }' is not assignable to type 'string | number'. +dependentDestructuredVariablesReferenceInDeclaration1.ts(25,11): error TS2339: Property 'c' does not exist on type 'string | number'. +dependentDestructuredVariablesReferenceInDeclaration1.ts(25,14): error TS2339: Property 'f' does not exist on type 'string | number'. +dependentDestructuredVariablesReferenceInDeclaration1.ts(25,17): error TS2339: Property 'f' does not exist on type 'string | number'. +dependentDestructuredVariablesReferenceInDeclaration1.ts(30,14): error TS7022: 'f' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. +dependentDestructuredVariablesReferenceInDeclaration1.ts(30,71): error TS2448: Block-scoped variable 'f' used before its declaration. +dependentDestructuredVariablesReferenceInDeclaration1.ts(58,14): error TS2451: Cannot redeclare block-scoped variable 'f'. +dependentDestructuredVariablesReferenceInDeclaration1.ts(58,17): error TS2451: Cannot redeclare block-scoped variable 'f'. -==== dependentDestructuredVariablesRefereinceInDeclaration1.ts (26 errors) ==== +==== dependentDestructuredVariablesReferenceInDeclaration1.ts (26 errors) ==== // https://github.com/microsoft/TypeScript/issues/62993 { @@ -41,7 +41,7 @@ dependentDestructuredVariablesRefereinceInDeclaration1.ts(58,17): error TS2451: !!! error TS7022: 'f' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. ~ !!! error TS2448: Block-scoped variable 'f' used before its declaration. -!!! related TS2728 dependentDestructuredVariablesRefereinceInDeclaration1.ts:4:14: 'f' is declared here. +!!! related TS2728 dependentDestructuredVariablesReferenceInDeclaration1.ts:4:14: 'f' is declared here. f; } @@ -106,7 +106,7 @@ dependentDestructuredVariablesRefereinceInDeclaration1.ts(58,17): error TS2451: !!! error TS7022: 'f' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. ~ !!! error TS2448: Block-scoped variable 'f' used before its declaration. -!!! related TS2728 dependentDestructuredVariablesRefereinceInDeclaration1.ts:30:14: 'f' is declared here. +!!! related TS2728 dependentDestructuredVariablesReferenceInDeclaration1.ts:30:14: 'f' is declared here. f; } diff --git a/testdata/baselines/reference/conformance/dependentDestructuredVariablesReferenceInDeclaration1.symbols b/testdata/baselines/reference/conformance/dependentDestructuredVariablesReferenceInDeclaration1.symbols new file mode 100644 index 00000000000..dd70a6b10cf --- /dev/null +++ b/testdata/baselines/reference/conformance/dependentDestructuredVariablesReferenceInDeclaration1.symbols @@ -0,0 +1,175 @@ +//// [tests/cases/conformance/controlFlow/dependentDestructuredVariablesReferenceInDeclaration1.ts] //// + +=== dependentDestructuredVariablesReferenceInDeclaration1.ts === +// https://github.com/microsoft/TypeScript/issues/62993 + +{ + const { c, f }: string | number = { c: 0, f }; +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 3, 9)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 3, 12)) +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 3, 37)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 3, 43)) + + f; +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 3, 12)) +} + +{ + const { c, f }: string | number = { c: 0, f: () => f }; +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 8, 9)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 8, 12)) +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 8, 37)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 8, 43)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 8, 12)) + + f; +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 8, 12)) +} + +{ + const { c, f, g = f }: string | number = { c: 0, f: 0, g: 0 }; +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 13, 9)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 13, 12)) +>g : Symbol(g, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 13, 15)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 13, 12)) +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 13, 44)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 13, 50)) +>g : Symbol(g, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 13, 56)) + + f; +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 13, 12)) + + g; +>g : Symbol(g, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 13, 15)) +} + +{ + const { c, f, f }: string | number = { c: 0, f: 0 }; +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 19, 9)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 19, 12)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 19, 15)) +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 19, 40)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 19, 46)) + + f; +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 19, 12)) +} + +{ + const { c, f, f: g }: string | number = { c: 0, f: 0 }; +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 24, 9)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 24, 12)) +>g : Symbol(g, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 24, 15)) +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 24, 43)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 24, 49)) + + g; +>g : Symbol(g, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 24, 15)) +} + +{ + const { c, f }: { c: 0; f: number } | { c: 1; f: string } = { c: 0, f }; +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 29, 9)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 29, 12)) +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 29, 19)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 29, 25)) +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 29, 41)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 29, 47)) +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 29, 63)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 29, 69)) + + f; +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 29, 12)) +} + +{ + const { c, f }: { c: 0; f: () => unknown } | { c: 1; f: string } = { +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 34, 9)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 34, 12)) +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 34, 19)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 34, 25)) +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 34, 48)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 34, 54)) + + c: 0, +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 34, 70)) + + f: () => f, +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 35, 9)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 34, 12)) + + }; + f; +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 34, 12)) +} + +{ + const { + c, +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 42, 9)) + + f, +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 43, 6)) + + g = f, +>g : Symbol(g, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 44, 6)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 43, 6)) + + }: + | { c: 0; f: bigint; g?: bigint | number } +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 47, 7)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 47, 13)) +>g : Symbol(g, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 47, 24)) + + | { c: 1; f: number; g: string } = { +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 48, 7)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 48, 13)) +>g : Symbol(g, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 48, 24)) + + c: 0, +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 48, 40)) + + f: 10n, +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 49, 9)) + + }; + f; +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 43, 6)) + + g; +>g : Symbol(g, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 44, 6)) +} + +{ + const { c, f, f }: { c: 0; f: number } | { c: 1; f: string } = { c: 0, f: 0 }; +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 57, 9)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 57, 12)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 57, 15)) +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 57, 22)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 57, 28)) +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 57, 44)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 57, 50)) +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 57, 66)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 57, 72)) + + f; +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 57, 12)) +} + +{ + const { c, f, f: g }: { c: 0; f: number } | { c: 1; f: string } = { c: 0, f: 0 }; +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 62, 9)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 62, 12)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 62, 31), Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 62, 53)) +>g : Symbol(g, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 62, 15)) +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 62, 25)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 62, 31)) +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 62, 47)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 62, 53)) +>c : Symbol(c, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 62, 69)) +>f : Symbol(f, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 62, 75)) + + g; +>g : Symbol(g, Decl(dependentDestructuredVariablesReferenceInDeclaration1.ts, 62, 15)) +} + diff --git a/testdata/baselines/reference/conformance/dependentDestructuredVariablesRefereinceInDeclaration1.types b/testdata/baselines/reference/conformance/dependentDestructuredVariablesReferenceInDeclaration1.types similarity index 89% rename from testdata/baselines/reference/conformance/dependentDestructuredVariablesRefereinceInDeclaration1.types rename to testdata/baselines/reference/conformance/dependentDestructuredVariablesReferenceInDeclaration1.types index fc6d6b8a603..1e1c61a2697 100644 --- a/testdata/baselines/reference/conformance/dependentDestructuredVariablesRefereinceInDeclaration1.types +++ b/testdata/baselines/reference/conformance/dependentDestructuredVariablesReferenceInDeclaration1.types @@ -1,6 +1,6 @@ -//// [tests/cases/conformance/controlFlow/dependentDestructuredVariablesRefereinceInDeclaration1.ts] //// +//// [tests/cases/conformance/controlFlow/dependentDestructuredVariablesReferenceInDeclaration1.ts] //// -=== dependentDestructuredVariablesRefereinceInDeclaration1.ts === +=== dependentDestructuredVariablesReferenceInDeclaration1.ts === // https://github.com/microsoft/TypeScript/issues/62993 { diff --git a/testdata/tests/cases/compiler/exhaustiveSwitchTupleLengthFallthrough.ts b/testdata/tests/cases/compiler/exhaustiveSwitchTupleLengthFallthrough.ts new file mode 100644 index 00000000000..6ca5e3bbadc --- /dev/null +++ b/testdata/tests/cases/compiler/exhaustiveSwitchTupleLengthFallthrough.ts @@ -0,0 +1,20 @@ +// @strict: true +// @noEmit: true + +type F = + | readonly [0, readonly [number]] + | readonly [0 | 1, readonly [number, number]] + | readonly [1, readonly [number, number, number]]; + +const f = ([i, x]: F): undefined => { + switch (i) { + case 0: { + switch (x.length) { + case 1: case 2: return undefined; + } + } + case 1: { + const _: 2 | 3 = x.length; + } + } +}; diff --git a/testdata/tests/cases/conformance/controlFlow/dependentDestructuredVariablesRefereinceInDeclaration1.ts b/testdata/tests/cases/conformance/controlFlow/dependentDestructuredVariablesReferenceInDeclaration1.ts similarity index 100% rename from testdata/tests/cases/conformance/controlFlow/dependentDestructuredVariablesRefereinceInDeclaration1.ts rename to testdata/tests/cases/conformance/controlFlow/dependentDestructuredVariablesReferenceInDeclaration1.ts From 68af56e8328e5ecd8d72f147bd2864f4099a0a40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Wed, 22 Jul 2026 17:38:40 +0200 Subject: [PATCH 9/9] update baseline --- .../dependentDestructuredVariablesNoCrash3.errors.txt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash3.errors.txt b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash3.errors.txt index 3fc104f3523..913ddaa10cf 100644 --- a/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash3.errors.txt +++ b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash3.errors.txt @@ -1,4 +1,4 @@ -error TS-1: Pre-emit (6) and post-emit (5) diagnostic counts do not match! This can indicate that a semantic _error_ was added by the emit resolver - such an error may not be reflected on the command line or in the editor, but may be captured in a baseline here! +dependentDestructuredVariablesNoCrash3.ts(3,7): error TS2488: Type 'boolean' must have a '[Symbol.iterator]()' method that returns an iterator. dependentDestructuredVariablesNoCrash3.ts(3,30): error TS7022: 'string' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. dependentDestructuredVariablesNoCrash3.ts(3,69): error TS2593: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i --save-dev @types/jest` or `npm i --save-dev @types/mocha` and then add 'jest' or 'mocha' to the types field in your tsconfig. dependentDestructuredVariablesNoCrash3.ts(3,86): error TS2448: Block-scoped variable 'string' used before its declaration. @@ -6,13 +6,12 @@ dependentDestructuredVariablesNoCrash3.ts(3,95): error TS1109: Expression expect dependentDestructuredVariablesNoCrash3.ts(3,97): error TS2339: Property 'ranges' does not exist on type 'boolean'. -!!! error TS-1: Pre-emit (6) and post-emit (5) diagnostic counts do not match! This can indicate that a semantic _error_ was added by the emit resolver - such an error may not be reflected on the command line or in the editor, but may be captured in a baseline here! -!!! related TS-1: The excess diagnostics are: -!!! related TS2488 dependentDestructuredVariablesNoCrash3.ts:3:7: Type 'boolean' must have a '[Symbol.iterator]()' method that returns an iterator. -==== dependentDestructuredVariablesNoCrash3.ts (5 errors) ==== +==== dependentDestructuredVariablesNoCrash3.ts (6 errors) ==== // https://github.com/microsoft/TypeScript/issues/63093 const [r0Def, r0, r1Def, as, string, r1, r2, r3Def, r3]: boolean = (test as number < string > ).ranges(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2488: Type 'boolean' must have a '[Symbol.iterator]()' method that returns an iterator. ~~~~~~ !!! error TS7022: 'string' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. ~~~~