Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 12 additions & 17 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30838,7 +30838,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
function getNarrowedTypeOfSymbol(symbol: Symbol, location: Identifier) {
const type = getTypeOfSymbol(symbol);
const declaration = symbol.valueDeclaration;
if (declaration) {
if (declaration && !textRangeContainsPositionInclusive(getRootDeclaration(declaration), location.pos)) {
// 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
// for the destructuring is a union type, one or more of the binding elements may represent discriminant
Expand Down Expand Up @@ -30866,23 +30866,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const parent = declaration.parent.parent;
const rootDeclaration = getRootDeclaration(parent);
if (rootDeclaration.kind === SyntaxKind.VariableDeclaration && getCombinedNodeFlagsCached(rootDeclaration) & NodeFlags.Constant || rootDeclaration.kind === SyntaxKind.Parameter) {
const links = getNodeLinks(parent);
if (!(links.flags & NodeCheckFlags.InCheckIdentifier)) {
links.flags |= NodeCheckFlags.InCheckIdentifier;
const parentType = getTypeForBindingElementParent(parent, CheckMode.Normal);
const parentTypeConstraint = parentType && mapType(parentType, getBaseConstraintOrType);
links.flags &= ~NodeCheckFlags.InCheckIdentifier;
if (parentTypeConstraint && parentTypeConstraint.flags & TypeFlags.Union && !(rootDeclaration.kind === SyntaxKind.Parameter && isSomeSymbolAssigned(rootDeclaration))) {
const pattern = declaration.parent;
const narrowedType = getFlowTypeOfReference(pattern, parentTypeConstraint, parentTypeConstraint, /*flowContainer*/ undefined, location.flowNode);
if (narrowedType.flags & TypeFlags.Never) {
return neverType;
}
// 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].
return getBindingElementTypeFromParentType(declaration, narrowedType, /*noTupleBoundsCheck*/ true);
const parentType = getTypeForBindingElementParent(parent, CheckMode.Normal);
const parentTypeConstraint = parentType && mapType(parentType, getBaseConstraintOrType);
if (parentTypeConstraint && parentTypeConstraint.flags & TypeFlags.Union && !(rootDeclaration.kind === SyntaxKind.Parameter && isSomeSymbolAssigned(rootDeclaration))) {
const pattern = declaration.parent;
const narrowedType = getFlowTypeOfReference(pattern, parentTypeConstraint, parentTypeConstraint, /*flowContainer*/ undefined, location.flowNode);
if (narrowedType.flags & TypeFlags.Never) {
return neverType;
}
// 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].
return getBindingElementTypeFromParentType(declaration, narrowedType, /*noTupleBoundsCheck*/ true);
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6240,8 +6240,7 @@ export const enum NodeCheckFlags {
ConstructorReference = 1 << 29, // Binding to a class constructor inside of the class's body.
ContainsClassWithPrivateIdentifiers = 1 << 20, // Marked on all block-scoped containers containing a class with private identifiers.
ContainsSuperPropertyInStaticInitializer = 1 << 21, // Marked on all block-scoped containers containing a static initializer with 'super.x' or 'super[x]'.
InCheckIdentifier = 1 << 22,
PartiallyTypeChecked = 1 << 23, // Node has been partially type checked
PartiallyTypeChecked = 1 << 22, // Node has been partially type checked

/** These flags are LazyNodeCheckFlags and can be calculated lazily by `hasNodeCheckFlag` */
LazyFlags = SuperInstance
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
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;
}
Loading