mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-15 12:51:30 -05:00
Merge pull request #29576 from Microsoft/fixContextuallyTypedParameters
Fix inference for contextually typed parameters with initializers
This commit is contained in:
@@ -4866,17 +4866,8 @@ namespace ts {
|
||||
function getTypeForBindingElement(declaration: BindingElement): Type | undefined {
|
||||
const pattern = declaration.parent;
|
||||
let parentType = getTypeForBindingElementParent(pattern.parent);
|
||||
// If parent has the unknown (error) type, then so does this binding element
|
||||
if (parentType === errorType) {
|
||||
return errorType;
|
||||
}
|
||||
// If no type was specified or inferred for parent,
|
||||
// infer from the initializer of the binding element if one is present.
|
||||
// Otherwise, go with the undefined type of the parent.
|
||||
if (!parentType) {
|
||||
return declaration.initializer ? checkDeclarationInitializer(declaration) : parentType;
|
||||
}
|
||||
if (isTypeAny(parentType)) {
|
||||
// If no type or an any type was inferred for parent, infer that for the binding element
|
||||
if (!parentType || isTypeAny(parentType)) {
|
||||
return parentType;
|
||||
}
|
||||
// Relax null check on ambient destructuring parameters, since the parameters have no implementation and are just documentation
|
||||
@@ -4962,6 +4953,12 @@ namespace ts {
|
||||
return strictNullChecks && optional ? getOptionalType(type) : type;
|
||||
}
|
||||
|
||||
function isParameterOfContextuallyTypedFunction(node: Declaration) {
|
||||
return node.kind === SyntaxKind.Parameter &&
|
||||
(node.parent.kind === SyntaxKind.FunctionExpression || node.parent.kind === SyntaxKind.ArrowFunction) &&
|
||||
!!getContextualType(<Expression>node.parent);
|
||||
}
|
||||
|
||||
// Return the inferred type for a variable, parameter, or property declaration
|
||||
function getTypeForVariableLikeDeclaration(declaration: ParameterDeclaration | PropertyDeclaration | PropertySignature | VariableDeclaration | BindingElement, includeOptionality: boolean): Type | undefined {
|
||||
// A variable declared in a for..in statement is of type string, or of type keyof T when the
|
||||
@@ -5045,8 +5042,9 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
// Use the type of the initializer expression if one is present
|
||||
if (declaration.initializer) {
|
||||
// Use the type of the initializer expression if one is present and the declaration is
|
||||
// not a parameter of a contextually typed function
|
||||
if (declaration.initializer && !isParameterOfContextuallyTypedFunction(declaration)) {
|
||||
const type = checkDeclarationInitializer(declaration);
|
||||
return addOptionality(type, isOptional);
|
||||
}
|
||||
@@ -5057,8 +5055,9 @@ namespace ts {
|
||||
return trueType;
|
||||
}
|
||||
|
||||
// If the declaration specifies a binding pattern, use the type implied by the binding pattern
|
||||
if (isBindingPattern(declaration.name)) {
|
||||
// If the declaration specifies a binding pattern and is not a parameter of a contextually
|
||||
// typed function, use the type implied by the binding pattern
|
||||
if (isBindingPattern(declaration.name) && !isParameterOfContextuallyTypedFunction(declaration)) {
|
||||
return getTypeFromBindingPattern(declaration.name, /*includePatternInType*/ false, /*reportErrors*/ true);
|
||||
}
|
||||
|
||||
@@ -5695,17 +5694,21 @@ namespace ts {
|
||||
}
|
||||
|
||||
function reportCircularityError(symbol: Symbol) {
|
||||
const declaration = <VariableLikeDeclaration>symbol.valueDeclaration;
|
||||
// Check if variable has type annotation that circularly references the variable itself
|
||||
if (getEffectiveTypeAnnotationNode(<VariableLikeDeclaration>symbol.valueDeclaration)) {
|
||||
if (getEffectiveTypeAnnotationNode(declaration)) {
|
||||
error(symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation,
|
||||
symbolToString(symbol));
|
||||
return errorType;
|
||||
}
|
||||
// Otherwise variable has initializer that circularly references the variable itself
|
||||
if (noImplicitAny) {
|
||||
// Check if variable has initializer that circularly references the variable itself
|
||||
if (noImplicitAny && (declaration.kind !== SyntaxKind.Parameter || (<HasInitializer>declaration).initializer)) {
|
||||
error(symbol.valueDeclaration, Diagnostics._0_implicitly_has_type_any_because_it_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer,
|
||||
symbolToString(symbol));
|
||||
}
|
||||
// Circularities could also result from parameters in function expressions that end up
|
||||
// having themselves as contextual types following type argument inference. In those cases
|
||||
// we have already reported an implicit any error so we don't report anything here.
|
||||
return anyType;
|
||||
}
|
||||
|
||||
@@ -25680,7 +25683,7 @@ namespace ts {
|
||||
const parent = node.parent.parent;
|
||||
const parentType = getTypeForBindingElementParent(parent);
|
||||
const name = node.propertyName || node.name;
|
||||
if (!isBindingPattern(name) && parentType) {
|
||||
if (parentType && !isBindingPattern(name)) {
|
||||
const exprType = getLiteralTypeFromPropertyName(name);
|
||||
if (isTypeUsableAsPropertyName(exprType)) {
|
||||
const nameText = getPropertyNameFromType(exprType);
|
||||
|
||||
Reference in New Issue
Block a user