@@ -7890,7 +7890,7 @@ namespace ts {
7890
7890
}
7891
7891
7892
7892
function getSimplifiedTypeOrConstraint(type: Type) {
7893
- const simplified = getSimplifiedType(type, /*writing*/ false );
7893
+ const simplified = getSimplifiedType(type);
7894
7894
return simplified !== type ? simplified : getConstraintOfType(type);
7895
7895
}
7896
7896
@@ -7935,7 +7935,7 @@ namespace ts {
7935
7935
// a union - once negated types exist and are applied to the conditional false branch, this "constraint"
7936
7936
// likely doesn't need to exist.
7937
7937
if (type.root.isDistributive && type.restrictiveInstantiation !== type) {
7938
- const simplified = getSimplifiedType(type.checkType, /*writing*/ false );
7938
+ const simplified = getSimplifiedType(type.checkType);
7939
7939
const constraint = simplified === type.checkType ? getConstraintOfType(simplified) : simplified;
7940
7940
if (constraint && constraint !== type.checkType) {
7941
7941
const mapper = makeUnaryTypeMapper(type.root.checkType, constraint);
@@ -8037,7 +8037,7 @@ namespace ts {
8037
8037
return t.immediateBaseConstraint = noConstraintType;
8038
8038
}
8039
8039
constraintDepth++;
8040
- let result = computeBaseConstraint(getSimplifiedType(t, /*writing*/ false ));
8040
+ let result = computeBaseConstraint(getSimplifiedType(t));
8041
8041
constraintDepth--;
8042
8042
if (!popTypeResolution()) {
8043
8043
if (t.flags & TypeFlags.TypeParameter) {
@@ -10253,9 +10253,23 @@ namespace ts {
10253
10253
const type = <IndexedAccessType>createType(TypeFlags.IndexedAccess);
10254
10254
type.objectType = objectType;
10255
10255
type.indexType = indexType;
10256
+ type.writing = false;
10256
10257
return type;
10257
10258
}
10258
10259
10260
+ function getWritingIndexedAccessType(type: IndexedAccessType) {
10261
+ const id = "w," + type.objectType.id + "," + type.indexType.id;
10262
+ let writeType = indexedAccessTypes.get(id);
10263
+ if (!writeType) {
10264
+ writeType = <IndexedAccessType>createType(TypeFlags.IndexedAccess);
10265
+ writeType.objectType = type.objectType;
10266
+ writeType.indexType = type.indexType;
10267
+ writeType.writing = true;
10268
+ indexedAccessTypes.set(id, writeType);
10269
+ }
10270
+ return writeType;
10271
+ }
10272
+
10259
10273
/**
10260
10274
* Returns if a type is or consists of a JSLiteral object type
10261
10275
* In addition to objects which are directly literals,
@@ -10462,9 +10476,9 @@ namespace ts {
10462
10476
return !!(type.flags & TypeFlags.TypeParameter && (<TypeParameter>type).isThisType);
10463
10477
}
10464
10478
10465
- function getSimplifiedType(type: Type, writing: boolean ): Type {
10466
- return type.flags & TypeFlags.IndexedAccess ? getSimplifiedIndexedAccessType(<IndexedAccessType>type, writing ) :
10467
- type.flags & TypeFlags.Conditional ? getSimplifiedConditionalType(<ConditionalType>type, writing ) :
10479
+ function getSimplifiedType(type: Type): Type {
10480
+ return type.flags & TypeFlags.IndexedAccess ? getSimplifiedIndexedAccessType(<IndexedAccessType>type) :
10481
+ type.flags & TypeFlags.Conditional ? getSimplifiedConditionalType(<ConditionalType>type) :
10468
10482
type;
10469
10483
}
10470
10484
@@ -10473,7 +10487,7 @@ namespace ts {
10473
10487
// (T | U)[K] -> T[K] & U[K] (writing)
10474
10488
// (T & U)[K] -> T[K] & U[K]
10475
10489
if (objectType.flags & TypeFlags.UnionOrIntersection) {
10476
- const types = map((objectType as UnionOrIntersectionType).types, t => getSimplifiedType(getIndexedAccessType(t, indexType), writing ));
10490
+ const types = map((objectType as UnionOrIntersectionType).types, t => getSimplifiedType(getIndexedAccessType(t, indexType)));
10477
10491
return objectType.flags & TypeFlags.Intersection || writing ? getIntersectionType(types) : getUnionType(types);
10478
10492
}
10479
10493
}
@@ -10482,24 +10496,25 @@ namespace ts {
10482
10496
// T[A | B] -> T[A] | T[B] (reading)
10483
10497
// T[A | B] -> T[A] & T[B] (writing)
10484
10498
if (indexType.flags & TypeFlags.Union) {
10485
- const types = map((indexType as UnionType).types, t => getSimplifiedType(getIndexedAccessType(objectType, t), writing ));
10499
+ const types = map((indexType as UnionType).types, t => getSimplifiedType(getIndexedAccessType(objectType, t)));
10486
10500
return writing ? getIntersectionType(types) : getUnionType(types);
10487
10501
}
10488
10502
}
10489
10503
10490
10504
// Transform an indexed access to a simpler form, if possible. Return the simpler form, or return
10491
10505
// the type itself if no transformation is possible. The writing flag indicates that the type is
10492
10506
// the target of an assignment.
10493
- function getSimplifiedIndexedAccessType(type: IndexedAccessType, writing: boolean): Type {
10507
+ function getSimplifiedIndexedAccessType(type: IndexedAccessType): Type {
10508
+ const writing = type.writing;
10494
10509
const cache = writing ? "simplifiedForWriting" : "simplifiedForReading";
10495
10510
if (type[cache]) {
10496
10511
return type[cache] === circularConstraintType ? type : type[cache]!;
10497
10512
}
10498
10513
type[cache] = circularConstraintType;
10499
10514
// We recursively simplify the object type as it may in turn be an indexed access type. For example, with
10500
10515
// '{ [P in T]: { [Q in U]: number } }[T][U]' we want to first simplify the inner indexed access type.
10501
- const objectType = getSimplifiedType(type.objectType, writing );
10502
- const indexType = getSimplifiedType(type.indexType, writing );
10516
+ const objectType = getSimplifiedType(type.objectType);
10517
+ const indexType = getSimplifiedType(type.indexType);
10503
10518
// T[A | B] -> T[A] | T[B] (reading)
10504
10519
// T[A | B] -> T[A] & T[B] (writing)
10505
10520
const distributedOverIndex = distributeObjectOverIndexType(objectType, indexType, writing);
@@ -10523,20 +10538,20 @@ namespace ts {
10523
10538
// that substitutes the index type for P. For example, for an index access { [P in K]: Box<T[P]> }[X], we
10524
10539
// construct the type Box<T[X]>.
10525
10540
if (isGenericMappedType(objectType)) {
10526
- return type[cache] = mapType(substituteIndexedMappedType(objectType, type.indexType), t => getSimplifiedType(t, writing ));
10541
+ return type[cache] = mapType(substituteIndexedMappedType(objectType, type.indexType), t => getSimplifiedType(t));
10527
10542
}
10528
10543
return type[cache] = type;
10529
10544
}
10530
10545
10531
- function getSimplifiedConditionalType(type: ConditionalType, writing: boolean ) {
10546
+ function getSimplifiedConditionalType(type: ConditionalType) {
10532
10547
const checkType = type.checkType;
10533
10548
const extendsType = type.extendsType;
10534
10549
const trueType = getTrueTypeFromConditionalType(type);
10535
10550
const falseType = getFalseTypeFromConditionalType(type);
10536
10551
// Simplifications for types of the form `T extends U ? T : never` and `T extends U ? never : T`.
10537
10552
if (falseType.flags & TypeFlags.Never && getActualTypeVariable(trueType) === getActualTypeVariable(checkType)) {
10538
10553
if (checkType.flags & TypeFlags.Any || isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(extendsType))) { // Always true
10539
- return getSimplifiedType(trueType, writing );
10554
+ return getSimplifiedType(trueType);
10540
10555
}
10541
10556
else if (isIntersectionEmpty(checkType, extendsType)) { // Always false
10542
10557
return neverType;
@@ -10547,7 +10562,7 @@ namespace ts {
10547
10562
return neverType;
10548
10563
}
10549
10564
else if (checkType.flags & TypeFlags.Any || isIntersectionEmpty(checkType, extendsType)) { // Always false
10550
- return getSimplifiedType(falseType, writing );
10565
+ return getSimplifiedType(falseType);
10551
10566
}
10552
10567
}
10553
10568
return type;
@@ -10589,7 +10604,7 @@ namespace ts {
10589
10604
return objectType;
10590
10605
}
10591
10606
// Defer the operation by creating an indexed access type.
10592
- const id = objectType.id + "," + indexType.id;
10607
+ const id = "r," + objectType.id + "," + indexType.id;
10593
10608
let type = indexedAccessTypes.get(id);
10594
10609
if (!type) {
10595
10610
indexedAccessTypes.set(id, type = createIndexedAccessType(objectType, indexType));
@@ -12812,10 +12827,10 @@ namespace ts {
12812
12827
target = (<SubstitutionType>target).typeVariable;
12813
12828
}
12814
12829
if (source.flags & TypeFlags.Simplifiable) {
12815
- source = getSimplifiedType(source, /*writing*/ false );
12830
+ source = getSimplifiedType(source);
12816
12831
}
12817
12832
if (target.flags & TypeFlags.Simplifiable) {
12818
- target = getSimplifiedType(target, /*writing*/ true );
12833
+ target = getSimplifiedType(target);
12819
12834
}
12820
12835
12821
12836
// Try to see if we're relating something like `Foo` -> `Bar | null | undefined`.
@@ -15653,16 +15668,16 @@ namespace ts {
15653
15668
}
15654
15669
else {
15655
15670
// Infer to the simplified version of an indexed access, if possible, to (hopefully) expose more bare type parameters to the inference engine
15656
- const simplified = getSimplifiedType(target, /*writing*/ false );
15671
+ const simplified = getSimplifiedType(target);
15657
15672
if (simplified !== target) {
15658
15673
invokeOnce(source, simplified, inferFromTypes);
15659
15674
}
15660
15675
else if (target.flags & TypeFlags.IndexedAccess) {
15661
- const indexType = getSimplifiedType((target as IndexedAccessType).indexType, /*writing*/ false );
15676
+ const indexType = getSimplifiedType((target as IndexedAccessType).indexType);
15662
15677
// Generally simplifications of instantiable indexes are avoided to keep relationship checking correct, however if our target is an access, we can consider
15663
15678
// that key of that access to be "instantiated", since we're looking to find the infernce goal in any way we can.
15664
15679
if (indexType.flags & TypeFlags.Instantiable) {
15665
- const simplified = distributeIndexOverObjectType(getSimplifiedType((target as IndexedAccessType).objectType, /*writing*/ false ), indexType, /*writing*/ false );
15680
+ const simplified = distributeIndexOverObjectType(getSimplifiedType((target as IndexedAccessType).objectType), indexType, (target as IndexedAccessType).writing );
15666
15681
if (simplified && simplified !== target) {
15667
15682
invokeOnce(source, simplified, inferFromTypes);
15668
15683
}
@@ -24738,6 +24753,7 @@ namespace ts {
24738
24753
if (checkReferenceExpression(left, Diagnostics.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access)
24739
24754
&& (!isIdentifier(left) || unescapeLeadingUnderscores(left.escapedText) !== "exports")) {
24740
24755
// to avoid cascading errors check assignability only if 'isReference' check succeeded and no errors were reported
24756
+ leftType = leftType.flags & TypeFlags.IndexedAccess ? getWritingIndexedAccessType(<IndexedAccessType>leftType) : leftType;
24741
24757
checkTypeAssignableToAndOptionallyElaborate(valueType, leftType, left, right);
24742
24758
}
24743
24759
}
0 commit comments