Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3d3825e

Browse files
authored
Fix multiple issues with indexed access types applied to mapped types (#47109)
* Fix multiple issues with indexed access types applied to mapped types* Add tests
1 parent7e0e867 commit3d3825e

File tree

5 files changed

+1667
-19
lines changed

5 files changed

+1667
-19
lines changed

‎src/compiler/checker.ts‎

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12048,13 +12048,24 @@ namespace ts {
1204812048
return type;
1204912049
}
1205012050

12051+
function isMappedTypeGenericIndexedAccess(type: Type) {
12052+
return type.flags & TypeFlags.IndexedAccess && getObjectFlags((type as IndexedAccessType).objectType) & ObjectFlags.Mapped &&
12053+
!isGenericMappedType((type as IndexedAccessType).objectType) && isGenericIndexType((type as IndexedAccessType).indexType);
12054+
}
12055+
1205112056
/**
1205212057
* For a type parameter, return the base constraint of the type parameter. For the string, number,
1205312058
* boolean, and symbol primitive types, return the corresponding object types. Otherwise return the
1205412059
* type itself.
1205512060
*/
1205612061
function getApparentType(type: Type): Type {
12057-
const t = type.flags & TypeFlags.Instantiable ? getBaseConstraintOfType(type) || unknownType : type;
12062+
// We obtain the base constraint for all instantiable types, except indexed access types of the form
12063+
// { [P in K]: E }[X], where K is non-generic and X is generic. For those types, we instead substitute an
12064+
// instantiation of E where P is replaced with X. We do this because getBaseConstraintOfType directly
12065+
// lowers to an instantiation where X's constraint is substituted for X, which isn't always desirable.
12066+
const t = !(type.flags & TypeFlags.Instantiable) ? type :
12067+
isMappedTypeGenericIndexedAccess(type) ? substituteIndexedMappedType((type as IndexedAccessType).objectType as MappedType, (type as IndexedAccessType).indexType) :
12068+
getBaseConstraintOfType(type) || unknownType;
1205812069
return getObjectFlags(t) & ObjectFlags.Mapped ? getApparentTypeOfMappedType(t as MappedType) :
1205912070
t.flags & TypeFlags.Intersection ? getApparentTypeOfIntersectionType(t as IntersectionType) :
1206012071
t.flags & TypeFlags.StringLike ? globalStringType :
@@ -21845,12 +21856,14 @@ namespace ts {
2184521856
// not contain anyFunctionType when we come back to this argument for its second round
2184621857
// of inference. Also, we exclude inferences for silentNeverType (which is used as a wildcard
2184721858
// when constructing types from type parameters that had no inference candidates).
21848-
if (getObjectFlags(source) & ObjectFlags.NonInferrableType || source === nonInferrableAnyType || source === silentNeverType ||
21849-
(priority & InferencePriority.ReturnType && (source === autoType || source === autoArrayType)) || isFromInferenceBlockedSource(source)) {
21859+
if (source === nonInferrableAnyType || source === silentNeverType || (priority & InferencePriority.ReturnType && (source === autoType || source === autoArrayType)) || isFromInferenceBlockedSource(source)) {
2185021860
return;
2185121861
}
2185221862
const inference = getInferenceInfoForType(target);
2185321863
if (inference) {
21864+
if (getObjectFlags(source) & ObjectFlags.NonInferrableType) {
21865+
return;
21866+
}
2185421867
if (!inference.isFixed) {
2185521868
if (inference.priority === undefined || priority < inference.priority) {
2185621869
inference.candidates = undefined;
@@ -21881,21 +21894,19 @@ namespace ts {
2188121894
inferencePriority = Math.min(inferencePriority, priority);
2188221895
return;
2188321896
}
21884-
else {
21885-
// Infer to the simplified version of an indexed access, if possible, to (hopefully) expose more bare type parameters to the inference engine
21886-
const simplified = getSimplifiedType(target, /*writing*/ false);
21887-
if (simplified !== target) {
21888-
invokeOnce(source, simplified, inferFromTypes);
21889-
}
21890-
else if (target.flags & TypeFlags.IndexedAccess) {
21891-
const indexType = getSimplifiedType((target as IndexedAccessType).indexType, /*writing*/ false);
21892-
// Generally simplifications of instantiable indexes are avoided to keep relationship checking correct, however if our target is an access, we can consider
21893-
// that key of that access to be "instantiated", since we're looking to find the infernce goal in any way we can.
21894-
if (indexType.flags & TypeFlags.Instantiable) {
21895-
const simplified = distributeIndexOverObjectType(getSimplifiedType((target as IndexedAccessType).objectType, /*writing*/ false), indexType, /*writing*/ false);
21896-
if (simplified && simplified !== target) {
21897-
invokeOnce(source, simplified, inferFromTypes);
21898-
}
21897+
// Infer to the simplified version of an indexed access, if possible, to (hopefully) expose more bare type parameters to the inference engine
21898+
const simplified = getSimplifiedType(target, /*writing*/ false);
21899+
if (simplified !== target) {
21900+
inferFromTypes(source, simplified);
21901+
}
21902+
else if (target.flags & TypeFlags.IndexedAccess) {
21903+
const indexType = getSimplifiedType((target as IndexedAccessType).indexType, /*writing*/ false);
21904+
// Generally simplifications of instantiable indexes are avoided to keep relationship checking correct, however if our target is an access, we can consider
21905+
// that key of that access to be "instantiated", since we're looking to find the infernce goal in any way we can.
21906+
if (indexType.flags & TypeFlags.Instantiable) {
21907+
const simplified = distributeIndexOverObjectType(getSimplifiedType((target as IndexedAccessType).objectType, /*writing*/ false), indexType, /*writing*/ false);
21908+
if (simplified && simplified !== target) {
21909+
inferFromTypes(source, simplified);
2189921910
}
2190021911
}
2190121912
}
@@ -24929,7 +24940,7 @@ namespace ts {
2492924940
const substituteConstraints = !(checkMode && checkMode & CheckMode.Inferential) &&
2493024941
someType(type, isGenericTypeWithUnionConstraint) &&
2493124942
(isConstraintPosition(type, reference) || hasNonBindingPatternContextualTypeWithNoGenericTypes(reference));
24932-
return substituteConstraints ? mapType(type, t => t.flags & TypeFlags.Instantiable ? getBaseConstraintOrType(t) : t) : type;
24943+
return substituteConstraints ? mapType(type, t => t.flags & TypeFlags.Instantiable&& !isMappedTypeGenericIndexedAccess(t)? getBaseConstraintOrType(t) : t) : type;
2493324944
}
2493424945

2493524946
function isExportOrExportExpression(location: Node) {

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp