@@ -26519,7 +26519,7 @@ namespace ts {
26519
26519
if (result) {
26520
26520
return result;
26521
26521
}
26522
- if (!(contextFlags! & ContextFlags.SkipBindingPatterns) && isBindingPattern(declaration.name)) { // This is less a contextual type and more an implied shape - in some cases, this may be undesirable
26522
+ if (!(contextFlags! & ContextFlags.SkipBindingPatterns) && isBindingPattern(declaration.name) && declaration.name.elements.length > 0) {
26523
26523
return getTypeFromBindingPattern(declaration.name, /*includePatternInType*/ true, /*reportErrors*/ false);
26524
26524
}
26525
26525
}
@@ -27053,22 +27053,20 @@ namespace ts {
27053
27053
const inferenceContext = getInferenceContext(node);
27054
27054
// If no inferences have been made, nothing is gained from instantiating as type parameters
27055
27055
// would just be replaced with their defaults similar to the apparent type.
27056
- if (inferenceContext && some(inferenceContext.inferences, hasInferenceCandidates)) {
27056
+ if (inferenceContext && contextFlags! & ContextFlags.Signature && some(inferenceContext.inferences, hasInferenceCandidates)) {
27057
27057
// For contextual signatures we incorporate all inferences made so far, e.g. from return
27058
27058
// types as well as arguments to the left in a function call.
27059
- if (contextFlags && contextFlags & ContextFlags.Signature) {
27060
- return instantiateInstantiableTypes(contextualType, inferenceContext.nonFixingMapper);
27061
- }
27059
+ return instantiateInstantiableTypes(contextualType, inferenceContext.nonFixingMapper);
27060
+ }
27061
+ if (inferenceContext?.returnMapper) {
27062
27062
// For other purposes (e.g. determining whether to produce literal types) we only
27063
27063
// incorporate inferences made from the return type in a function call. We remove
27064
27064
// the 'boolean' type from the contextual type such that contextually typed boolean
27065
27065
// literals actually end up widening to 'boolean' (see #48363).
27066
- if (inferenceContext.returnMapper) {
27067
- const type = instantiateInstantiableTypes(contextualType, inferenceContext.returnMapper);
27068
- return type.flags & TypeFlags.Union && containsType((type as UnionType).types, regularFalseType) && containsType((type as UnionType).types, regularTrueType) ?
27069
- filterType(type, t => t !== regularFalseType && t !== regularTrueType) :
27070
- type;
27071
- }
27066
+ const type = instantiateInstantiableTypes(contextualType, inferenceContext.returnMapper);
27067
+ return type.flags & TypeFlags.Union && containsType((type as UnionType).types, regularFalseType) && containsType((type as UnionType).types, regularTrueType) ?
27068
+ filterType(type, t => t !== regularFalseType && t !== regularTrueType) :
27069
+ type;
27072
27070
}
27073
27071
}
27074
27072
return contextualType;
@@ -29904,29 +29902,43 @@ namespace ts {
29904
29902
// 'let f: (x: string) => number = wrap(s => s.length)', we infer from the declared type of 'f' to the
29905
29903
// return type of 'wrap'.
29906
29904
if (node.kind !== SyntaxKind.Decorator) {
29907
- const contextualType = getContextualType(node, every(signature.typeParameters, p => !!getDefaultFromTypeParameter(p)) ? ContextFlags.SkipBindingPatterns : ContextFlags.None);
29905
+ const skipBindingPatterns = every(signature.typeParameters, p => !!getDefaultFromTypeParameter(p));
29906
+ const contextualType = getContextualType(node, skipBindingPatterns ? ContextFlags.SkipBindingPatterns : ContextFlags.None);
29908
29907
if (contextualType) {
29909
29908
const inferenceTargetType = getReturnTypeOfSignature(signature);
29910
29909
if (couldContainTypeVariables(inferenceTargetType)) {
29911
- // We clone the inference context to avoid disturbing a resolution in progress for an
29912
- // outer call expression. Effectively we just want a snapshot of whatever has been
29913
- // inferred for any outer call expression so far.
29914
29910
const outerContext = getInferenceContext(node);
29915
- const outerMapper = getMapperFromContext(cloneInferenceContext(outerContext, InferenceFlags.NoDefault));
29916
- const instantiatedType = instantiateType(contextualType, outerMapper);
29917
- // If the contextual type is a generic function type with a single call signature, we
29918
- // instantiate the type with its own type parameters and type arguments. This ensures that
29919
- // the type parameters are not erased to type any during type inference such that they can
29920
- // be inferred as actual types from the contextual type. For example:
29921
- // declare function arrayMap<T, U>(f: (x: T) => U): (a: T[]) => U[];
29922
- // const boxElements: <A>(a: A[]) => { value: A }[] = arrayMap(value => ({ value }));
29923
- // Above, the type of the 'value' parameter is inferred to be 'A'.
29924
- const contextualSignature = getSingleCallSignature(instantiatedType);
29925
- const inferenceSourceType = contextualSignature && contextualSignature.typeParameters ?
29926
- getOrCreateTypeFromSignature(getSignatureInstantiationWithoutFillingInTypeArguments(contextualSignature, contextualSignature.typeParameters)) :
29927
- instantiatedType;
29928
- // Inferences made from return types have lower priority than all other inferences.
29929
- inferTypes(context.inferences, inferenceSourceType, inferenceTargetType, InferencePriority.ReturnType);
29911
+ const isFromBindingPattern = !skipBindingPatterns && getContextualType(node, ContextFlags.SkipBindingPatterns) !== contextualType;
29912
+ // A return type inference from a binding pattern can be used in instantiating the contextual
29913
+ // type of an argument later in inference, but cannot stand on its own as the final return type.
29914
+ // It is incorporated into `context.returnMapper` which is used in `instantiateContextualType`,
29915
+ // but doesn't need to go into `context.inferences`. This allows a an array binding pattern to
29916
+ // produce a tuple for `T` in
29917
+ // declare function f<T>(cb: () => T): T;
29918
+ // const [e1, e2, e3] = f(() => [1, "hi", true]);
29919
+ // but does not produce any inference for `T` in
29920
+ // declare function f<T>(): T;
29921
+ // const [e1, e2, e3] = f();
29922
+ if (!isFromBindingPattern) {
29923
+ // We clone the inference context to avoid disturbing a resolution in progress for an
29924
+ // outer call expression. Effectively we just want a snapshot of whatever has been
29925
+ // inferred for any outer call expression so far.
29926
+ const outerMapper = getMapperFromContext(cloneInferenceContext(outerContext, InferenceFlags.NoDefault));
29927
+ const instantiatedType = instantiateType(contextualType, outerMapper);
29928
+ // If the contextual type is a generic function type with a single call signature, we
29929
+ // instantiate the type with its own type parameters and type arguments. This ensures that
29930
+ // the type parameters are not erased to type any during type inference such that they can
29931
+ // be inferred as actual types from the contextual type. For example:
29932
+ // declare function arrayMap<T, U>(f: (x: T) => U): (a: T[]) => U[];
29933
+ // const boxElements: <A>(a: A[]) => { value: A }[] = arrayMap(value => ({ value }));
29934
+ // Above, the type of the 'value' parameter is inferred to be 'A'.
29935
+ const contextualSignature = getSingleCallSignature(instantiatedType);
29936
+ const inferenceSourceType = contextualSignature && contextualSignature.typeParameters ?
29937
+ getOrCreateTypeFromSignature(getSignatureInstantiationWithoutFillingInTypeArguments(contextualSignature, contextualSignature.typeParameters)) :
29938
+ instantiatedType;
29939
+ // Inferences made from return types have lower priority than all other inferences.
29940
+ inferTypes(context.inferences, inferenceSourceType, inferenceTargetType, InferencePriority.ReturnType);
29941
+ }
29930
29942
// Create a type mapper for instantiating generic contextual types using the inferences made
29931
29943
// from the return type. We need a separate inference pass here because (a) instantiation of
29932
29944
// the source type uses the outer context's return mapper (which excludes inferences made from
0 commit comments