diff --git a/internal/checker/checker.go b/internal/checker/checker.go index e2479e8bc23..f4c091a04cc 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -13701,8 +13701,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 { @@ -13712,6 +13719,8 @@ 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 narrowedType := c.getFlowTypeOfReferenceEx(pattern, parentTypeConstraint, parentTypeConstraint, nil /*flowContainer*/, getFlowNodeOfNode(location)) @@ -13724,7 +13733,6 @@ func (c *Checker) getNarrowedTypeOfSymbol(symbol *ast.Symbol, location *ast.Node 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/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/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/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/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/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/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..913ddaa10cf --- /dev/null +++ b/testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash3.errors.txt @@ -0,0 +1,26 @@ +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. +dependentDestructuredVariablesNoCrash3.ts(3,95): error TS1109: Expression expected. +dependentDestructuredVariablesNoCrash3.ts(3,97): error TS2339: Property 'ranges' does not exist on type 'boolean'. + + +==== 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. + ~~~~ +!!! 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/dependentDestructuredVariablesReferenceInDeclaration1.errors.txt b/testdata/baselines/reference/conformance/dependentDestructuredVariablesReferenceInDeclaration1.errors.txt new file mode 100644 index 00000000000..5529a3e5e68 --- /dev/null +++ b/testdata/baselines/reference/conformance/dependentDestructuredVariablesReferenceInDeclaration1.errors.txt @@ -0,0 +1,149 @@ +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'. + + +==== dependentDestructuredVariablesReferenceInDeclaration1.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 dependentDestructuredVariablesReferenceInDeclaration1.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 dependentDestructuredVariablesReferenceInDeclaration1.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/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/dependentDestructuredVariablesReferenceInDeclaration1.types b/testdata/baselines/reference/conformance/dependentDestructuredVariablesReferenceInDeclaration1.types new file mode 100644 index 00000000000..1e1c61a2697 --- /dev/null +++ b/testdata/baselines/reference/conformance/dependentDestructuredVariablesReferenceInDeclaration1.types @@ -0,0 +1,205 @@ +//// [tests/cases/conformance/controlFlow/dependentDestructuredVariablesReferenceInDeclaration1.ts] //// + +=== dependentDestructuredVariablesReferenceInDeclaration1.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/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/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(); 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(); + }, +}; 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/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/dependentDestructuredVariablesReferenceInDeclaration1.ts b/testdata/tests/cases/conformance/controlFlow/dependentDestructuredVariablesReferenceInDeclaration1.ts new file mode 100644 index 00000000000..d72cb155371 --- /dev/null +++ b/testdata/tests/cases/conformance/controlFlow/dependentDestructuredVariablesReferenceInDeclaration1.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; +}