@@ -1968,10 +1968,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1968
1968
var blockedStringType = createIntrinsicType(TypeFlags.Any, "any", /*objectFlags*/ undefined, "blocked string");
1969
1969
var errorType = createIntrinsicType(TypeFlags.Any, "error");
1970
1970
var unresolvedType = createIntrinsicType(TypeFlags.Any, "unresolved");
1971
- var nonInferrableAnyType = createIntrinsicType(TypeFlags.Any, "any", ObjectFlags.ContainsWideningType, "non-inferrable");
1972
1971
var intrinsicMarkerType = createIntrinsicType(TypeFlags.Any, "intrinsic");
1973
1972
var unknownType = createIntrinsicType(TypeFlags.Unknown, "unknown");
1974
1973
var nonNullUnknownType = createIntrinsicType(TypeFlags.Unknown, "unknown", /*objectFlags*/ undefined, "non-null");
1974
+ var nonInferrableUnknownType = createIntrinsicType(TypeFlags.Unknown, "unknown", ObjectFlags.ContainsWideningType, "non-inferrable");
1975
1975
var undefinedType = createIntrinsicType(TypeFlags.Undefined, "undefined");
1976
1976
var undefinedWideningType = strictNullChecks ? undefinedType : createIntrinsicType(TypeFlags.Undefined, "undefined", ObjectFlags.ContainsWideningType, "widening");
1977
1977
var missingType = createIntrinsicType(TypeFlags.Undefined, "undefined", /*objectFlags*/ undefined, "missing");
@@ -11444,10 +11444,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
11444
11444
reportImplicitAny(element, anyType);
11445
11445
}
11446
11446
// When we're including the pattern in the type (an indication we're obtaining a contextual type), we
11447
- // use a non-inferrable any type. Inference will never directly infer this type, but it is possible
11447
+ // use a non-inferrable unknown type. Inference will never directly infer this type, but it is possible
11448
11448
// to infer a type that contains it, e.g. for a binding pattern like [foo] or { foo }. In such cases,
11449
- // widening of the binding pattern type substitutes a regular any for the non-inferrable any .
11450
- return includePatternInType ? nonInferrableAnyType : anyType;
11449
+ // widening of the binding pattern type substitutes a regular any for the non-inferrable unknown .
11450
+ return includePatternInType ? nonInferrableUnknownType : anyType;
11451
11451
}
11452
11452
11453
11453
// Return the type implied by an object binding pattern
@@ -20905,7 +20905,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
20905
20905
function isSimpleTypeRelatedTo(source: Type, target: Type, relation: Map<string, RelationComparisonResult>, errorReporter?: ErrorReporter) {
20906
20906
const s = source.flags;
20907
20907
const t = target.flags;
20908
- if (t & TypeFlags.Any || s & TypeFlags.Never || source === wildcardType) return true;
20908
+ if (t & TypeFlags.Any || s & TypeFlags.Never || source === wildcardType || source === nonInferrableUnknownType ) return true;
20909
20909
if (t & TypeFlags.Unknown && !(relation === strictSubtypeRelation && s & TypeFlags.Any)) return true;
20910
20910
if (t & TypeFlags.Never) return false;
20911
20911
if (s & TypeFlags.StringLike && t & TypeFlags.String) return true;
@@ -24603,6 +24603,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
24603
24603
}
24604
24604
else if (isObjectLiteralType(type)) {
24605
24605
result = getWidenedTypeOfObjectLiteral(type, context);
24606
+ if (type.pattern) {
24607
+ result.pattern = type.pattern;
24608
+ }
24606
24609
}
24607
24610
else if (type.flags & TypeFlags.Union) {
24608
24611
const unionContext = context || createWideningContext(/*parent*/ undefined, /*propertyName*/ undefined, (type as UnionType).types);
@@ -24617,6 +24620,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
24617
24620
}
24618
24621
else if (isArrayOrTupleType(type)) {
24619
24622
result = createTypeReference(type.target, sameMap(getTypeArguments(type), getWidenedType));
24623
+ if (type.pattern) {
24624
+ result.pattern = type.pattern;
24625
+ }
24620
24626
}
24621
24627
if (result && context === undefined) {
24622
24628
type.widened = result;
@@ -25025,21 +25031,34 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
25025
25031
// For arrays and tuples we infer new arrays and tuples where the reverse mapping has been
25026
25032
// applied to the element type(s).
25027
25033
if (isArrayType(source)) {
25028
- return createArrayType(inferReverseMappedType(getTypeArguments(source)[0], target, constraint), isReadonlyArrayType(source));
25034
+ let reversed = createArrayType(inferReverseMappedType(getTypeArguments(source)[0], target, constraint), isReadonlyArrayType(source)) as TypeReference;
25035
+ if (source.pattern) {
25036
+ reversed = cloneTypeReference(reversed);
25037
+ reversed.pattern = source.pattern;
25038
+ }
25039
+ return reversed;
25029
25040
}
25030
25041
if (isTupleType(source)) {
25031
25042
const elementTypes = map(getElementTypes(source), t => inferReverseMappedType(t, target, constraint));
25032
25043
const elementFlags = getMappedTypeModifiers(target) & MappedTypeModifiers.IncludeOptional ?
25033
25044
sameMap(source.target.elementFlags, f => f & ElementFlags.Optional ? ElementFlags.Required : f) :
25034
25045
source.target.elementFlags;
25035
- return createTupleType(elementTypes, elementFlags, source.target.readonly, source.target.labeledElementDeclarations);
25046
+ let reversed = createTupleType(elementTypes, elementFlags, source.target.readonly, source.target.labeledElementDeclarations) as TypeReference;
25047
+ if (source.pattern) {
25048
+ reversed = cloneTypeReference(reversed);
25049
+ reversed.pattern = source.pattern;
25050
+ }
25051
+ return reversed;
25036
25052
}
25037
25053
// For all other object types we infer a new object type where the reverse mapping has been
25038
25054
// applied to the type of each property.
25039
25055
const reversed = createObjectType(ObjectFlags.ReverseMapped | ObjectFlags.Anonymous, /*symbol*/ undefined) as ReverseMappedType;
25040
25056
reversed.source = source;
25041
25057
reversed.mappedType = target;
25042
25058
reversed.constraintType = constraint;
25059
+ if (source.pattern) {
25060
+ reversed.pattern = source.pattern;
25061
+ }
25043
25062
return reversed;
25044
25063
}
25045
25064
@@ -25056,7 +25075,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
25056
25075
const templateType = getTemplateTypeFromMappedType(target);
25057
25076
const inference = createInferenceInfo(typeParameter);
25058
25077
inferTypes([inference], sourceType, templateType);
25059
- return getTypeFromInference(inference) || unknownType;
25078
+ return getTypeFromInference(inference) || (sourceType.pattern ? nonInferrableUnknownType : unknownType) ;
25060
25079
}
25061
25080
25062
25081
function* getUnmatchedProperties(source: Type, target: Type, requireOptionalProperties: boolean, matchDiscriminantProperties: boolean): IterableIterator<Symbol> {
@@ -25089,8 +25108,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
25089
25108
}
25090
25109
25091
25110
function tupleTypesDefinitelyUnrelated(source: TupleTypeReference, target: TupleTypeReference) {
25092
- return !(target.target.combinedFlags & ElementFlags.Variadic) && target.target.minLength > source.target.minLength ||
25093
- !target.target.hasRestElement && (source.target.hasRestElement || target.target.fixedLength < source.target.fixedLength);
25111
+ return !source.pattern && (! (target.target.combinedFlags & ElementFlags.Variadic) && target.target.minLength > source.target.minLength ||
25112
+ !target.target.hasRestElement && (source.target.hasRestElement || target.target.fixedLength < source.target.fixedLength)) ;
25094
25113
}
25095
25114
25096
25115
function typesDefinitelyUnrelated(source: Type, target: Type) {
@@ -25396,9 +25415,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
25396
25415
// This flag is infectious; if we produce Box<never> (where never is silentNeverType), Box<never> is
25397
25416
// also non-inferrable.
25398
25417
//
25399
- // As a special case, also ignore nonInferrableAnyType, which is a special form of the any type
25400
- // used as a stand-in for binding elements when they are being inferred.
25401
- if (getObjectFlags(source) & ObjectFlags.NonInferrableType || source === nonInferrableAnyType) {
25418
+ // As a special case, also ignore nonInferrableUnknownType, which is a special form of the unknown type
25419
+ // used as a stand-in for binding elements when they are being inferred. It is ignored as a direct inference candidate
25420
+ // but types containing it can be inferred.
25421
+ if (getObjectFlags(source) & ObjectFlags.NonInferrableType || source === nonInferrableUnknownType) {
25402
25422
return;
25403
25423
}
25404
25424
if (!inference.isFixed) {
@@ -26099,12 +26119,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
26099
26119
function getInferredType(context: InferenceContext, index: number): Type {
26100
26120
const inference = context.inferences[index];
26101
26121
if (!inference.inferredType) {
26122
+ let isFromBindingPattern = false;
26102
26123
let inferredType: Type | undefined;
26103
26124
let fallbackType: Type | undefined;
26104
26125
if (context.signature) {
26105
26126
const inferredCovariantType = inference.candidates ? getCovariantInference(inference, context.signature) : undefined;
26106
26127
const inferredContravariantType = inference.contraCandidates ? getContravariantInference(inference) : undefined;
26107
- if (inferredCovariantType || inferredContravariantType) {
26128
+ if (!inferredContravariantType && inference.candidates?.length === 1 && inference.candidates[0].pattern) {
26129
+ isFromBindingPattern = true;
26130
+ inferredType = inferredCovariantType;
26131
+ }
26132
+ else if (inferredCovariantType || inferredContravariantType) {
26108
26133
// If we have both co- and contra-variant inferences, we prefer the co-variant inference if it is not 'never',
26109
26134
// all co-variant inferences are subtypes of it (i.e. it isn't one of a conflicting set of candidates), it is
26110
26135
// a subtype of some contra-variant inference, and no other type parameter is constrained to this type parameter
@@ -26145,7 +26170,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
26145
26170
const constraint = getConstraintOfTypeParameter(inference.typeParameter);
26146
26171
if (constraint) {
26147
26172
const instantiatedConstraint = instantiateType(constraint, context.nonFixingMapper);
26148
- if (!inferredType || !context.compareTypes(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) {
26173
+ if (isFromBindingPattern) {
26174
+ inference.inferredType = getIntersectionType([inference.inferredType, instantiatedConstraint]);
26175
+ }
26176
+ else if (!inferredType || !context.compareTypes(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) {
26149
26177
// If the fallback type satisfies the constraint, we pick it. Otherwise, we pick the constraint.
26150
26178
inference.inferredType = fallbackType && context.compareTypes(fallbackType, getTypeWithThisArgument(instantiatedConstraint, fallbackType)) ? fallbackType : instantiatedConstraint;
26151
26179
}
@@ -30279,7 +30307,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
30279
30307
else if (t.flags & TypeFlags.StructuredType) {
30280
30308
const prop = getPropertyOfType(t, name);
30281
30309
if (prop) {
30282
- return isCircularMappedProperty(prop) ? undefined : removeMissingType(getTypeOfSymbol(prop), !!(prop && prop.flags & SymbolFlags.Optional));
30310
+ if (isCircularMappedProperty(prop)) {
30311
+ return undefined;
30312
+ }
30313
+ const type = getTypeOfSymbol(prop);
30314
+ if (type !== nonInferrableUnknownType) {
30315
+ return removeMissingType(type, !!(prop && prop.flags & SymbolFlags.Optional));
30316
+ }
30317
+ if (t.flags & TypeFlags.Intersection) {
30318
+ t = getIntersectionType((t as IntersectionType).types.filter(t => !t.pattern));
30319
+ }
30283
30320
}
30284
30321
if (isTupleType(t) && isNumericLiteralName(name) && +name >= 0) {
30285
30322
const restType = getElementTypeOfSliceOfTupleType(t, t.target.fixedLength, /*endSkipCount*/ 0, /*writing*/ false, /*noReductions*/ true);
@@ -31248,7 +31285,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
31248
31285
31249
31286
pushCachedContextualType(node);
31250
31287
const contextualType = getApparentTypeOfContextualType(node, /*contextFlags*/ undefined);
31251
- const contextualTypeHasPattern = contextualType && contextualType.pattern &&
31288
+ const contextualTypeHasPattern = !(checkMode & CheckMode.Inferential) && contextualType && contextualType.pattern &&
31252
31289
(contextualType.pattern.kind === SyntaxKind.ObjectBindingPattern || contextualType.pattern.kind === SyntaxKind.ObjectLiteralExpression);
31253
31290
const inConstContext = isConstContext(node);
31254
31291
const checkFlags = inConstContext ? CheckFlags.Readonly : 0;
0 commit comments