@@ -14887,10 +14887,22 @@ namespace ts {
14887
14887
return type;
14888
14888
}
14889
14889
14890
+ // We consider a type to be partially inferable if it isn't marked non-inferable or if it is
14891
+ // an object literal type with at least one property of an inferable type. For example, an object
14892
+ // literal { a: 123, b: x => true } is marked non-inferable because it contains a context sensitive
14893
+ // arrow function, but is considered partially inferable because property 'a' has an inferable type.
14894
+ function isPartiallyInferableType(type: Type): boolean {
14895
+ return !(getObjectFlags(type) & ObjectFlags.NonInferrableType) ||
14896
+ isObjectLiteralType(type) && some(getPropertiesOfType(type), prop => isPartiallyInferableType(getTypeOfSymbol(prop)));
14897
+ }
14898
+
14890
14899
function createReverseMappedType(source: Type, target: MappedType, constraint: IndexType) {
14891
- // If any property contains context sensitive functions that have been skipped, the source type
14892
- // is incomplete and we can't infer a meaningful input type.
14893
- if (getObjectFlags(source) & ObjectFlags.NonInferrableType || getPropertiesOfType(source).length === 0 && !getIndexInfoOfType(source, IndexKind.String)) {
14900
+ // We consider a source type reverse mappable if it has a string index signature or if
14901
+ // it has one or more properties and all properties have inferable types.
14902
+ const properties = getPropertiesOfType(source);
14903
+ const isReverseMappable = getIndexInfoOfType(source, IndexKind.String) ||
14904
+ properties.length !== 0 && every(properties, prop => isPartiallyInferableType(getTypeOfSymbol(prop)));
14905
+ if (!isReverseMappable) {
14894
14906
return undefined;
14895
14907
}
14896
14908
// For arrays and tuples we infer new arrays and tuples where the reverse mapping has been
0 commit comments