@@ -640,14 +640,15 @@ namespace ts {
640
640
const identityRelation = createMap<RelationComparisonResult>();
641
641
const enumRelation = createMap<RelationComparisonResult>();
642
642
643
- type TypeSystemEntity = Symbol | Type | Signature;
643
+ type TypeSystemEntity = Node | Symbol | Type | Signature;
644
644
645
645
const enum TypeSystemPropertyName {
646
646
Type,
647
647
ResolvedBaseConstructorType,
648
648
DeclaredType,
649
649
ResolvedReturnType,
650
650
ImmediateBaseConstraint,
651
+ EnumTagType,
651
652
}
652
653
653
654
const enum CheckMode {
@@ -3470,8 +3471,8 @@ namespace ts {
3470
3471
const arity = getTypeReferenceArity(type);
3471
3472
const tupleConstituentNodes = mapToTypeNodes(typeArguments.slice(0, arity), context);
3472
3473
const hasRestElement = (<TupleType>type.target).hasRestElement;
3473
- if (tupleConstituentNodes && tupleConstituentNodes.length > 0 ) {
3474
- for (let i = (<TupleType>type.target).minLength; i < arity; i++) {
3474
+ if (tupleConstituentNodes) {
3475
+ for (let i = (<TupleType>type.target).minLength; i < Math.min( arity, tupleConstituentNodes.length) ; i++) {
3475
3476
tupleConstituentNodes[i] = hasRestElement && i === arity - 1 ?
3476
3477
createRestTypeNode(createArrayTypeNode(tupleConstituentNodes[i])) :
3477
3478
createOptionalTypeNode(tupleConstituentNodes[i]);
@@ -4475,6 +4476,8 @@ namespace ts {
4475
4476
switch (propertyName) {
4476
4477
case TypeSystemPropertyName.Type:
4477
4478
return !!getSymbolLinks(<Symbol>target).type;
4479
+ case TypeSystemPropertyName.EnumTagType:
4480
+ return !!(getNodeLinks(target as JSDocEnumTag).resolvedEnumType);
4478
4481
case TypeSystemPropertyName.DeclaredType:
4479
4482
return !!getSymbolLinks(<Symbol>target).declaredType;
4480
4483
case TypeSystemPropertyName.ResolvedBaseConstructorType:
@@ -8252,9 +8255,18 @@ namespace ts {
8252
8255
}
8253
8256
8254
8257
// JS are 'string' or 'number', not an enum type.
8255
- const enumTag = symbol.valueDeclaration && getJSDocEnumTag(symbol.valueDeclaration);
8258
+ const enumTag = isInJSFile(node) && symbol.valueDeclaration && getJSDocEnumTag(symbol.valueDeclaration);
8256
8259
if (enumTag) {
8257
- return enumTag.typeExpression ? getTypeFromTypeNode(enumTag.typeExpression) : errorType;
8260
+ const links = getNodeLinks(enumTag);
8261
+ if (!pushTypeResolution(enumTag, TypeSystemPropertyName.EnumTagType)) {
8262
+ return errorType;
8263
+ }
8264
+ let type = enumTag.typeExpression ? getTypeFromTypeNode(enumTag.typeExpression) : errorType;
8265
+ if (!popTypeResolution()) {
8266
+ type = errorType;
8267
+ error(node, Diagnostics.Enum_type_0_circularly_references_itself, symbolToString(symbol));
8268
+ }
8269
+ return (links.resolvedEnumType = type);
8258
8270
}
8259
8271
8260
8272
// Get type from reference to named type that cannot be generic (enum or type parameter)
@@ -13373,7 +13385,7 @@ namespace ts {
13373
13385
let propagationType: Type;
13374
13386
inferFromTypes(originalSource, originalTarget);
13375
13387
13376
- function inferFromTypes(source: Type, target: Type) {
13388
+ function inferFromTypes(source: Type, target: Type): void {
13377
13389
if (!couldContainTypeVariables(target)) {
13378
13390
return;
13379
13391
}
@@ -13508,6 +13520,9 @@ namespace ts {
13508
13520
inferFromTypes(getTrueTypeFromConditionalType(<ConditionalType>source), getTrueTypeFromConditionalType(<ConditionalType>target));
13509
13521
inferFromTypes(getFalseTypeFromConditionalType(<ConditionalType>source), getFalseTypeFromConditionalType(<ConditionalType>target));
13510
13522
}
13523
+ else if (target.flags & TypeFlags.Conditional) {
13524
+ inferFromTypes(source, getUnionType([getTrueTypeFromConditionalType(<ConditionalType>target), getFalseTypeFromConditionalType(<ConditionalType>target)]));
13525
+ }
13511
13526
else if (target.flags & TypeFlags.UnionOrIntersection) {
13512
13527
const targetTypes = (<UnionOrIntersectionType>target).types;
13513
13528
let typeVariableCount = 0;
@@ -13541,7 +13556,14 @@ namespace ts {
13541
13556
}
13542
13557
else {
13543
13558
if (!(priority & InferencePriority.NoConstraints && source.flags & (TypeFlags.Intersection | TypeFlags.Instantiable))) {
13544
- source = getApparentType(source);
13559
+ const apparentSource = getApparentType(source);
13560
+ // getApparentType can return _any_ type, since an indexed access or conditional may simplify to any other type.
13561
+ // If that occurs and it doesn't simplify to an object or intersection, we'll need to restart `inferFromTypes`
13562
+ // with the simplified source.
13563
+ if (apparentSource !== source && !(apparentSource.flags & (TypeFlags.Object | TypeFlags.Intersection))) {
13564
+ return inferFromTypes(apparentSource, target);
13565
+ }
13566
+ source = apparentSource;
13545
13567
}
13546
13568
if (source.flags & (TypeFlags.Object | TypeFlags.Intersection)) {
13547
13569
const key = source.id + "," + target.id;
@@ -13747,7 +13769,7 @@ namespace ts {
13747
13769
13748
13770
function hasPrimitiveConstraint(type: TypeParameter): boolean {
13749
13771
const constraint = getConstraintOfTypeParameter(type);
13750
- return !!constraint && maybeTypeOfKind(constraint, TypeFlags.Primitive | TypeFlags.Index);
13772
+ return !!constraint && maybeTypeOfKind(constraint.flags & TypeFlags.Conditional ? getDefaultConstraintOfConditionalType(constraint as ConditionalType) : constraint , TypeFlags.Primitive | TypeFlags.Index);
13751
13773
}
13752
13774
13753
13775
function isObjectLiteralType(type: Type) {
@@ -14734,6 +14756,14 @@ namespace ts {
14734
14756
// reference 'x.y.z', we may be at an assignment to 'x.y' or 'x'. In that case,
14735
14757
// return the declared type.
14736
14758
if (containsMatchingReference(reference, node)) {
14759
+ // A matching dotted name might also be an expando property on a function *expression*,
14760
+ // in which case we continue control flow analysis back to the function's declaration
14761
+ if (isVariableDeclaration(node) && (isInJSFile(node) || isVarConst(node))) {
14762
+ const init = getDeclaredExpandoInitializer(node);
14763
+ if (init && (init.kind === SyntaxKind.FunctionExpression || init.kind === SyntaxKind.ArrowFunction)) {
14764
+ return getTypeAtFlowNode(flow.antecedent);
14765
+ }
14766
+ }
14737
14767
return declaredType;
14738
14768
}
14739
14769
// Assignment doesn't affect reference
@@ -18208,7 +18238,7 @@ namespace ts {
18208
18238
// Referencing abstract properties within their own constructors is not allowed
18209
18239
if ((flags & ModifierFlags.Abstract) && isThisProperty(node) && symbolHasNonMethodDeclaration(prop)) {
18210
18240
const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)!);
18211
- if (declaringClassDeclaration && isNodeUsedDuringClassInitialization(node, declaringClassDeclaration )) {
18241
+ if (declaringClassDeclaration && isNodeUsedDuringClassInitialization(node)) {
18212
18242
error(errorNode, Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_the_constructor, symbolToString(prop), getTextOfIdentifierOrLiteral(declaringClassDeclaration.name!)); // TODO: GH#18217
18213
18243
return false;
18214
18244
}
@@ -18395,6 +18425,9 @@ namespace ts {
18395
18425
}
18396
18426
}
18397
18427
}
18428
+ else if (strictNullChecks && prop && prop.valueDeclaration && isPropertyAccessExpression(prop.valueDeclaration) && getAssignmentDeclarationPropertyAccessKind(prop.valueDeclaration)) {
18429
+ assumeUninitialized = true;
18430
+ }
18398
18431
const flowType = getFlowTypeOfReference(node, propType, assumeUninitialized ? getOptionalType(propType) : propType);
18399
18432
if (assumeUninitialized && !(getFalsyFlags(propType) & TypeFlags.Undefined) && getFalsyFlags(flowType) & TypeFlags.Undefined) {
18400
18433
error(right, Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(prop!)); // TODO: GH#18217
@@ -20192,18 +20225,15 @@ namespace ts {
20192
20225
assigned || inferred;
20193
20226
}
20194
20227
20195
- function getAssignedClassType(symbol: Symbol) {
20228
+ function getAssignedClassType(symbol: Symbol): Type | undefined {
20196
20229
const decl = symbol.valueDeclaration;
20197
20230
const assignmentSymbol = decl && decl.parent &&
20198
20231
(isFunctionDeclaration(decl) && getSymbolOfNode(decl) ||
20199
20232
isBinaryExpression(decl.parent) && getSymbolOfNode(decl.parent.left) ||
20200
20233
isVariableDeclaration(decl.parent) && getSymbolOfNode(decl.parent));
20201
- if (assignmentSymbol) {
20202
- const prototype = forEach(assignmentSymbol.declarations, getAssignedJSPrototype);
20203
- if (prototype) {
20204
- return checkExpression(prototype);
20205
- }
20206
- }
20234
+ const prototype = assignmentSymbol && assignmentSymbol.exports && assignmentSymbol.exports.get("prototype" as __String);
20235
+ const init = prototype && getAssignedJSPrototype(prototype.valueDeclaration);
20236
+ return init ? checkExpression(init) : undefined;
20207
20237
}
20208
20238
20209
20239
function getAssignedJSPrototype(node: Node) {
@@ -27419,12 +27449,12 @@ namespace ts {
27419
27449
return result;
27420
27450
}
27421
27451
27422
- function isNodeUsedDuringClassInitialization(node: Node, classDeclaration: ClassLikeDeclaration ) {
27452
+ function isNodeUsedDuringClassInitialization(node: Node) {
27423
27453
return !!findAncestor(node, element => {
27424
- if (( isConstructorDeclaration(element) && nodeIsPresent(element.body) || isPropertyDeclaration(element)) && element.parent === classDeclaration ) {
27454
+ if (isConstructorDeclaration(element) && nodeIsPresent(element.body) || isPropertyDeclaration(element)) {
27425
27455
return true;
27426
27456
}
27427
- else if (element === classDeclaration || isFunctionLikeDeclaration(element)) {
27457
+ else if (isClassLike( element) || isFunctionLikeDeclaration(element)) {
27428
27458
return "quit";
27429
27459
}
27430
27460
0 commit comments