@@ -2673,7 +2673,7 @@ namespace ts {
2673
2673
}
2674
2674
Debug.assert(bindingElement.kind === SyntaxKind.BindingElement);
2675
2675
if (bindingElement.propertyName) {
2676
- writer.writeSymbol (getTextOfNode(bindingElement.propertyName), bindingElement.symbol );
2676
+ writer.writeProperty (getTextOfNode(bindingElement.propertyName));
2677
2677
writePunctuation(writer, SyntaxKind.ColonToken);
2678
2678
writeSpace(writer);
2679
2679
}
@@ -4523,7 +4523,7 @@ namespace ts {
4523
4523
// First, if the constraint type is a type parameter, obtain the base constraint. Then,
4524
4524
// if the key type is a 'keyof X', obtain 'keyof C' where C is the base constraint of X.
4525
4525
// Finally, iterate over the constituents of the resulting iteration type.
4526
- const keyType = constraintType.flags & TypeFlags.TypeParameter ? getApparentType(constraintType) : constraintType;
4526
+ const keyType = constraintType.flags & TypeFlags.TypeVariable ? getApparentType(constraintType) : constraintType;
4527
4527
const iterationType = keyType.flags & TypeFlags.Index ? getIndexType(getApparentType((<IndexType>keyType).type)) : keyType;
4528
4528
forEachType(iterationType, t => {
4529
4529
// Create a mapper from T to the current iteration type constituent. Then, if the
@@ -4579,7 +4579,7 @@ namespace ts {
4579
4579
function isGenericMappedType(type: Type) {
4580
4580
if (getObjectFlags(type) & ObjectFlags.Mapped) {
4581
4581
const constraintType = getConstraintTypeFromMappedType(<MappedType>type);
4582
- return !! (constraintType.flags & ( TypeFlags.TypeParameter | TypeFlags.Index) );
4582
+ return maybeTypeOfKind (constraintType, TypeFlags.TypeVariable | TypeFlags.Index);
4583
4583
}
4584
4584
return false;
4585
4585
}
@@ -5912,7 +5912,7 @@ namespace ts {
5912
5912
return links.resolvedType;
5913
5913
}
5914
5914
5915
- function getIndexTypeForTypeVariable (type: TypeVariable) {
5915
+ function getIndexTypeForGenericType (type: TypeVariable | UnionOrIntersectionType ) {
5916
5916
if (!type.resolvedIndexType) {
5917
5917
type.resolvedIndexType = <IndexType>createType(TypeFlags.Index);
5918
5918
type.resolvedIndexType.type = type;
@@ -5931,7 +5931,7 @@ namespace ts {
5931
5931
}
5932
5932
5933
5933
function getIndexType(type: Type): Type {
5934
- return type.flags & TypeFlags.TypeVariable ? getIndexTypeForTypeVariable (<TypeVariable>type) :
5934
+ return maybeTypeOfKind( type, TypeFlags.TypeVariable) ? getIndexTypeForGenericType (<TypeVariable | UnionOrIntersectionType >type) :
5935
5935
getObjectFlags(type) & ObjectFlags.Mapped ? getConstraintTypeFromMappedType(<MappedType>type) :
5936
5936
type.flags & TypeFlags.Any || getIndexInfoOfType(type, IndexKind.String) ? stringType :
5937
5937
getLiteralTypeFromPropertyNames(type);
@@ -6032,14 +6032,14 @@ namespace ts {
6032
6032
}
6033
6033
6034
6034
function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode) {
6035
- if (indexType.flags & TypeFlags.TypeVariable ||
6036
- objectType.flags & TypeFlags.TypeVariable && indexType.flags & TypeFlags.Index ||
6037
- isGenericMappedType(objectType)) {
6038
- // If the object type is a type variable (a type parameter or another indexed access type), if the
6039
- // index type is a type variable or an index type, or if the object type is a mapped type with a
6040
- // generic constraint, we are performing a higher-order index access where we cannot meaningfully
6041
- // access the properties of the object type. In those cases, we first check that the index type is
6042
- // assignable to 'keyof T' for the object type.
6035
+ if (maybeTypeOfKind( indexType, TypeFlags.TypeVariable | TypeFlags.Index) || isGenericMappedType(objectType)) {
6036
+ if ( objectType.flags & TypeFlags.Any) {
6037
+ return objectType;
6038
+ }
6039
+ // If the index type is generic or if the object type is a mapped type with a generic constraint,
6040
+ // we are performing a higher-order index access where we cannot meaningfully access the properties
6041
+ // of the object type. In those cases, we first check that the index type is assignable to 'keyof T'
6042
+ // for the object type.
6043
6043
if (accessNode) {
6044
6044
if (!isTypeAssignableTo(indexType, getIndexType(objectType))) {
6045
6045
error(accessNode, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(objectType));
@@ -6539,7 +6539,7 @@ namespace ts {
6539
6539
// union type A | undefined, we produce { [P in keyof A]: X } | undefined.
6540
6540
const constraintType = getConstraintTypeFromMappedType(type);
6541
6541
if (constraintType.flags & TypeFlags.Index) {
6542
- const typeVariable = <TypeParameter> (<IndexType>constraintType).type;
6542
+ const typeVariable = (<IndexType>constraintType).type;
6543
6543
const mappedTypeVariable = instantiateType(typeVariable, mapper);
6544
6544
if (typeVariable !== mappedTypeVariable) {
6545
6545
return mapType(mappedTypeVariable, t => {
@@ -8706,12 +8706,15 @@ namespace ts {
8706
8706
if (constraintType.flags & TypeFlags.Index) {
8707
8707
// We're inferring from some source type S to a homomorphic mapped type { [P in keyof T]: X },
8708
8708
// where T is a type variable. Use inferTypeForHomomorphicMappedType to infer a suitable source
8709
- // type and then infer from that type to T.
8709
+ // type and then make a secondary inference from that type to T. We make a secondary inference
8710
+ // such that direct inferences to T get priority over inferences to Partial<T>, for example.
8710
8711
const index = indexOf(typeVariables, (<IndexType>constraintType).type);
8711
8712
if (index >= 0 && !typeInferences[index].isFixed) {
8712
8713
const inferredType = inferTypeForHomomorphicMappedType(source, <MappedType>target);
8713
8714
if (inferredType) {
8715
+ inferiority++;
8714
8716
inferFromTypes(inferredType, typeVariables[index]);
8717
+ inferiority--;
8715
8718
}
8716
8719
}
8717
8720
return;
@@ -10402,33 +10405,37 @@ namespace ts {
10402
10405
return baseConstructorType === nullWideningType;
10403
10406
}
10404
10407
10408
+ function checkThisBeforeSuper(node: Node, container: Node, diagnosticMessage: DiagnosticMessage) {
10409
+ const containingClassDecl = <ClassDeclaration>container.parent;
10410
+ const baseTypeNode = getClassExtendsHeritageClauseElement(containingClassDecl);
10411
+
10412
+ // If a containing class does not have extends clause or the class extends null
10413
+ // skip checking whether super statement is called before "this" accessing.
10414
+ if (baseTypeNode && !classDeclarationExtendsNull(containingClassDecl)) {
10415
+ const superCall = getSuperCallInConstructor(<ConstructorDeclaration>container);
10416
+
10417
+ // We should give an error in the following cases:
10418
+ // - No super-call
10419
+ // - "this" is accessing before super-call.
10420
+ // i.e super(this)
10421
+ // this.x; super();
10422
+ // We want to make sure that super-call is done before accessing "this" so that
10423
+ // "this" is not accessed as a parameter of the super-call.
10424
+ if (!superCall || superCall.end > node.pos) {
10425
+ // In ES6, super inside constructor of class-declaration has to precede "this" accessing
10426
+ error(node, diagnosticMessage);
10427
+ }
10428
+ }
10429
+ }
10430
+
10405
10431
function checkThisExpression(node: Node): Type {
10406
10432
// Stop at the first arrow function so that we can
10407
10433
// tell whether 'this' needs to be captured.
10408
10434
let container = getThisContainer(node, /* includeArrowFunctions */ true);
10409
10435
let needToCaptureLexicalThis = false;
10410
10436
10411
10437
if (container.kind === SyntaxKind.Constructor) {
10412
- const containingClassDecl = <ClassDeclaration>container.parent;
10413
- const baseTypeNode = getClassExtendsHeritageClauseElement(containingClassDecl);
10414
-
10415
- // If a containing class does not have extends clause or the class extends null
10416
- // skip checking whether super statement is called before "this" accessing.
10417
- if (baseTypeNode && !classDeclarationExtendsNull(containingClassDecl)) {
10418
- const superCall = getSuperCallInConstructor(<ConstructorDeclaration>container);
10419
-
10420
- // We should give an error in the following cases:
10421
- // - No super-call
10422
- // - "this" is accessing before super-call.
10423
- // i.e super(this)
10424
- // this.x; super();
10425
- // We want to make sure that super-call is done before accessing "this" so that
10426
- // "this" is not accessed as a parameter of the super-call.
10427
- if (!superCall || superCall.end > node.pos) {
10428
- // In ES6, super inside constructor of class-declaration has to precede "this" accessing
10429
- error(node, Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class);
10430
- }
10431
- }
10438
+ checkThisBeforeSuper(node, container, Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class);
10432
10439
}
10433
10440
10434
10441
// Now skip arrow functions to get the "real" owner of 'this'.
@@ -10576,6 +10583,10 @@ namespace ts {
10576
10583
return unknownType;
10577
10584
}
10578
10585
10586
+ if (!isCallExpression && container.kind === SyntaxKind.Constructor) {
10587
+ checkThisBeforeSuper(node, container, Diagnostics.super_must_be_called_before_accessing_a_property_of_super_in_the_constructor_of_a_derived_class);
10588
+ }
10589
+
10579
10590
if ((getModifierFlags(container) & ModifierFlags.Static) || isCallExpression) {
10580
10591
nodeCheckFlag = NodeCheckFlags.SuperStatic;
10581
10592
}
@@ -16196,7 +16207,7 @@ namespace ts {
16196
16207
return undefined;
16197
16208
}
16198
16209
16199
- const onfulfilledParameterType = getTypeWithFacts(getUnionType(map(thenSignatures, getTypeOfFirstParameterOfSignature)), TypeFacts.NEUndefined );
16210
+ const onfulfilledParameterType = getTypeWithFacts(getUnionType(map(thenSignatures, getTypeOfFirstParameterOfSignature)), TypeFacts.NEUndefinedOrNull );
16200
16211
if (isTypeAny(onfulfilledParameterType)) {
16201
16212
return undefined;
16202
16213
}
0 commit comments