mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-15 21:36:50 -05:00
Destructuring declaration prefers type annotation type (#25282)
* Destructuring declaration prefers type annotation type Previously, getTypeForBindingElement would always union the declarations type and the type of the default initializer. Now, if the declaration has a type annotation, it does not union with the initializer type. The type annotation's type is the one used. * Small cleanup in parentDeclarationHasTypeAnnotation * Refactoring based on PR comments * Combine getCombined*Flags into a single helper function Retain the individual functions since they are used a lot. * Remove unneeded temp
This commit is contained in:
committed by
GitHub
parent
950593b669
commit
5c2eeb20b1
@@ -4161,7 +4161,7 @@ namespace ts {
|
||||
}
|
||||
const parent = getDeclarationContainer(node);
|
||||
// If the node is not exported or it is not ambient module element (except import declaration)
|
||||
if (!(getCombinedModifierFlags(node) & ModifierFlags.Export) &&
|
||||
if (!(getCombinedModifierFlags(node as Declaration) & ModifierFlags.Export) &&
|
||||
!(node.kind !== SyntaxKind.ImportEqualsDeclaration && parent.kind !== SyntaxKind.SourceFile && parent.flags & NodeFlags.Ambient)) {
|
||||
return isGlobalSourceFile(parent);
|
||||
}
|
||||
@@ -4525,7 +4525,7 @@ namespace ts {
|
||||
if (strictNullChecks && declaration.initializer && !(getFalsyFlags(checkExpressionCached(declaration.initializer)) & TypeFlags.Undefined)) {
|
||||
type = getTypeWithFacts(type, TypeFacts.NEUndefined);
|
||||
}
|
||||
return declaration.initializer ?
|
||||
return declaration.initializer && !getEffectiveTypeAnnotationNode(walkUpBindingElementsAndPatterns(declaration)) ?
|
||||
getUnionType([type, checkExpressionCached(declaration.initializer)], UnionReduction.Subtype) :
|
||||
type;
|
||||
}
|
||||
@@ -22096,7 +22096,7 @@ namespace ts {
|
||||
return hasModifier(node, ModifierFlags.Private) && !!(node.flags & NodeFlags.Ambient);
|
||||
}
|
||||
|
||||
function getEffectiveDeclarationFlags(n: Node, flagsToCheck: ModifierFlags): ModifierFlags {
|
||||
function getEffectiveDeclarationFlags(n: Declaration, flagsToCheck: ModifierFlags): ModifierFlags {
|
||||
let flags = getCombinedModifierFlags(n);
|
||||
|
||||
// children of classes (even ambient classes) should not be marked as ambient or export
|
||||
|
||||
@@ -903,7 +903,7 @@ namespace ts {
|
||||
|
||||
export function isConst(node: Node): boolean {
|
||||
return !!(getCombinedNodeFlags(node) & NodeFlags.Const)
|
||||
|| !!(getCombinedModifierFlags(node) & ModifierFlags.Const);
|
||||
|| !!(isDeclaration(node) && getCombinedModifierFlags(node) & ModifierFlags.Const);
|
||||
}
|
||||
|
||||
export function isLet(node: Node): boolean {
|
||||
@@ -4605,33 +4605,36 @@ namespace ts {
|
||||
return isEmptyBindingPattern(node.name);
|
||||
}
|
||||
|
||||
function walkUpBindingElementsAndPatterns(node: Node): Node {
|
||||
while (node && (node.kind === SyntaxKind.BindingElement || isBindingPattern(node))) {
|
||||
node = node.parent;
|
||||
export function walkUpBindingElementsAndPatterns(binding: BindingElement): VariableDeclaration | ParameterDeclaration {
|
||||
let node = binding.parent;
|
||||
while (isBindingElement(node.parent)) {
|
||||
node = node.parent.parent;
|
||||
}
|
||||
|
||||
return node;
|
||||
return node.parent;
|
||||
}
|
||||
|
||||
export function getCombinedModifierFlags(node: Node): ModifierFlags {
|
||||
node = walkUpBindingElementsAndPatterns(node);
|
||||
let flags = getModifierFlags(node);
|
||||
function getCombinedFlags(node: Node, getFlags: (n: Node) => number): number {
|
||||
if (isBindingElement(node)) {
|
||||
node = walkUpBindingElementsAndPatterns(node);
|
||||
}
|
||||
let flags = getFlags(node);
|
||||
if (node.kind === SyntaxKind.VariableDeclaration) {
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
if (node && node.kind === SyntaxKind.VariableDeclarationList) {
|
||||
flags |= getModifierFlags(node);
|
||||
flags |= getFlags(node);
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
if (node && node.kind === SyntaxKind.VariableStatement) {
|
||||
flags |= getModifierFlags(node);
|
||||
flags |= getFlags(node);
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
export function getCombinedModifierFlags(node: Declaration): ModifierFlags {
|
||||
return getCombinedFlags(node, getModifierFlags);
|
||||
}
|
||||
|
||||
// Returns the node flags for this node and all relevant parent nodes. This is done so that
|
||||
// nodes like variable declarations and binding elements can returned a view of their flags
|
||||
// that includes the modifiers from their container. i.e. flags like export/declare aren't
|
||||
@@ -4640,23 +4643,7 @@ namespace ts {
|
||||
// list. By calling this function, all those flags are combined so that the client can treat
|
||||
// the node as if it actually had those flags.
|
||||
export function getCombinedNodeFlags(node: Node): NodeFlags {
|
||||
node = walkUpBindingElementsAndPatterns(node);
|
||||
|
||||
let flags = node.flags;
|
||||
if (node.kind === SyntaxKind.VariableDeclaration) {
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
if (node && node.kind === SyntaxKind.VariableDeclarationList) {
|
||||
flags |= node.flags;
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
if (node && node.kind === SyntaxKind.VariableStatement) {
|
||||
flags |= node.flags;
|
||||
}
|
||||
|
||||
return flags;
|
||||
return getCombinedFlags(node, n => n.flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1044,7 +1044,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function getNodeModifiers(node: Node): string {
|
||||
const flags = getCombinedModifierFlags(node);
|
||||
const flags = isDeclaration(node) ? getCombinedModifierFlags(node) : ModifierFlags.None;
|
||||
const result: string[] = [];
|
||||
|
||||
if (flags & ModifierFlags.Private) result.push(ScriptElementKindModifier.privateMemberModifier);
|
||||
|
||||
Reference in New Issue
Block a user