@@ -763,6 +763,7 @@ import {
763
763
JSDocSatisfiesTag,
764
764
JSDocSignature,
765
765
JSDocTemplateTag,
766
+ JSDocTypeAssertion,
766
767
JSDocTypedefTag,
767
768
JSDocTypeExpression,
768
769
JSDocTypeLiteral,
@@ -1039,7 +1040,6 @@ import {
1039
1040
TypeReferenceSerializationKind,
1040
1041
TypeReferenceType,
1041
1042
TypeVariable,
1042
- UnaryExpression,
1043
1043
unescapeLeadingUnderscores,
1044
1044
UnionOrIntersectionType,
1045
1045
UnionOrIntersectionTypeNode,
@@ -19875,7 +19875,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
19875
19875
const restIndex = sourceRestType || targetRestType ? paramCount - 1 : -1;
19876
19876
19877
19877
for (let i = 0; i < paramCount; i++) {
19878
- const sourceType = i === restIndex ? getRestTypeAtPosition(source, i, /*readonly*/ true ) : tryGetTypeAtPosition(source, i);
19878
+ const sourceType = i === restIndex ? getRestTypeAtPosition(source, i) : tryGetTypeAtPosition(source, i);
19879
19879
const targetType = i === restIndex ? getRestTypeAtPosition(target, i) : tryGetTypeAtPosition(target, i);
19880
19880
if (sourceType && targetType) {
19881
19881
// In order to ensure that any generic type Foo<T> is at least co-variant with respect to T no matter
@@ -20899,14 +20899,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
20899
20899
if (containsType(targetTypes, source)) {
20900
20900
return Ternary.True;
20901
20901
}
20902
- if (getObjectFlags(target) & ObjectFlags.PrimitiveUnion && !(source.flags & TypeFlags.EnumLiteral) && (
20902
+ if (relation !== comparableRelation && getObjectFlags(target) & ObjectFlags.PrimitiveUnion && !(source.flags & TypeFlags.EnumLiteral) && (
20903
20903
source.flags & (TypeFlags.StringLiteral | TypeFlags.BooleanLiteral | TypeFlags.BigIntLiteral) ||
20904
20904
(relation === subtypeRelation || relation === strictSubtypeRelation) && source.flags & TypeFlags.NumberLiteral)) {
20905
20905
// When relating a literal type to a union of primitive types, we know the relation is false unless
20906
20906
// the union contains the base primitive type or the literal type in one of its fresh/regular forms.
20907
20907
// We exclude numeric literals for non-subtype relations because numeric literals are assignable to
20908
20908
// numeric enum literals with the same value. Similarly, we exclude enum literal types because
20909
- // identically named enum types are related (see isEmumTypeRelatedTo).
20909
+ // identically named enum types are related (see isEnumTypeRelatedTo). We exclude the comparable
20910
+ // relation in entirety because it needs to be checked in both directions.
20910
20911
const alternateForm = source === (source as StringLiteralType).regularType ? (source as StringLiteralType).freshType : (source as StringLiteralType).regularType;
20911
20912
const primitive = source.flags & TypeFlags.StringLiteral ? stringType :
20912
20913
source.flags & TypeFlags.NumberLiteral ? numberType :
@@ -22485,7 +22486,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
22485
22486
const targetHasStringIndex = some(indexInfos, info => info.keyType === stringType);
22486
22487
let result = Ternary.True;
22487
22488
for (const targetInfo of indexInfos) {
22488
- const related = !sourceIsPrimitive && targetHasStringIndex && targetInfo.type.flags & TypeFlags.Any ? Ternary.True :
22489
+ const related = relation !== strictSubtypeRelation && !sourceIsPrimitive && targetHasStringIndex && targetInfo.type.flags & TypeFlags.Any ? Ternary.True :
22489
22490
isGenericMappedType(source) && targetHasStringIndex ? isRelatedTo(getTemplateTypeFromMappedType(source), targetInfo.type, RecursionFlags.Both, reportErrors) :
22490
22491
typeRelatedToIndexInfo(source, targetInfo, reportErrors, intersectionState);
22491
22492
if (!related) {
@@ -25890,7 +25891,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
25890
25891
}
25891
25892
25892
25893
function isTypeSubsetOf(source: Type, target: Type) {
25893
- return source === target || target.flags & TypeFlags.Union && isTypeSubsetOfUnion(source, target as UnionType);
25894
+ return !!( source === target || source.flags & TypeFlags.Never || target.flags & TypeFlags.Union && isTypeSubsetOfUnion(source, target as UnionType) );
25894
25895
}
25895
25896
25896
25897
function isTypeSubsetOfUnion(source: Type, target: UnionType) {
@@ -26714,7 +26715,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
26714
26715
// If an antecedent type is not a subset of the declared type, we need to perform
26715
26716
// subtype reduction. This happens when a "foreign" type is injected into the control
26716
26717
// flow using the instanceof operator or a user defined type predicate.
26717
- if (!isTypeSubsetOf(type, declaredType )) {
26718
+ if (!isTypeSubsetOf(type, initialType )) {
26718
26719
subtypeReduction = true;
26719
26720
}
26720
26721
if (isIncomplete(flowType)) {
@@ -26732,7 +26733,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
26732
26733
return type;
26733
26734
}
26734
26735
antecedentTypes.push(type);
26735
- if (!isTypeSubsetOf(type, declaredType )) {
26736
+ if (!isTypeSubsetOf(type, initialType )) {
26736
26737
subtypeReduction = true;
26737
26738
}
26738
26739
if (isIncomplete(flowType)) {
@@ -26807,7 +26808,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
26807
26808
// If an antecedent type is not a subset of the declared type, we need to perform
26808
26809
// subtype reduction. This happens when a "foreign" type is injected into the control
26809
26810
// flow using the instanceof operator or a user defined type predicate.
26810
- if (!isTypeSubsetOf(type, declaredType )) {
26811
+ if (!isTypeSubsetOf(type, initialType )) {
26811
26812
subtypeReduction = true;
26812
26813
}
26813
26814
// If the type at a particular antecedent path is the declared type there is no
@@ -33983,10 +33984,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
33983
33984
return cached;
33984
33985
}
33985
33986
links.resolvedSignature = resolvingSignature;
33986
- const result = resolveSignature(node, candidatesOutArray, checkMode || CheckMode.Normal);
33987
+ let result = resolveSignature(node, candidatesOutArray, checkMode || CheckMode.Normal);
33987
33988
// When CheckMode.SkipGenericFunctions is set we use resolvingSignature to indicate that call
33988
33989
// resolution should be deferred.
33989
33990
if (result !== resolvingSignature) {
33991
+ // if the signature resolution originated on a node that itself depends on the contextual type
33992
+ // then it's possible that the resolved signature might not be the same as the one that would be computed in source order
33993
+ // since resolving such signature leads to resolving the potential outer signature, its arguments and thus the very same signature
33994
+ // it's possible that this inner resolution sets the resolvedSignature first.
33995
+ // In such a case we ignore the local result and reuse the correct one that was cached.
33996
+ if (links.resolvedSignature !== resolvingSignature) {
33997
+ result = links.resolvedSignature;
33998
+ }
33990
33999
// If signature resolution originated in control flow type analysis (for example to compute the
33991
34000
// assigned type in a flow assignment) we don't cache the result as it may be based on temporary
33992
34001
// types from the control flow analysis.
@@ -34357,14 +34366,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
34357
34366
return getReturnTypeOfSignature(signature);
34358
34367
}
34359
34368
34360
- function checkAssertion(node: AssertionExpression) {
34369
+ function checkAssertion(node: AssertionExpression, checkMode: CheckMode | undefined ) {
34361
34370
if (node.kind === SyntaxKind.TypeAssertionExpression) {
34362
34371
const file = getSourceFileOfNode(node);
34363
34372
if (file && fileExtensionIsOneOf(file.fileName, [Extension.Cts, Extension.Mts])) {
34364
34373
grammarErrorOnNode(node, Diagnostics.This_syntax_is_reserved_in_files_with_the_mts_or_cts_extension_Use_an_as_expression_instead);
34365
34374
}
34366
34375
}
34367
- return checkAssertionWorker(node, node.type, node.expression );
34376
+ return checkAssertionWorker(node, checkMode );
34368
34377
}
34369
34378
34370
34379
function isValidConstAssertionArgument(node: Node): boolean {
@@ -34395,16 +34404,42 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
34395
34404
return false;
34396
34405
}
34397
34406
34398
- function checkAssertionWorker(errNode: Node, type: TypeNode, expression: UnaryExpression | Expression, checkMode?: CheckMode) {
34399
- let exprType = checkExpression(expression, checkMode);
34407
+ function checkAssertionWorker(node: JSDocTypeAssertion | AssertionExpression, checkMode: CheckMode | undefined) {
34408
+ const { type, expression } = getAssertionTypeAndExpression(node);
34409
+ const exprType = checkExpression(expression, checkMode);
34400
34410
if (isConstTypeReference(type)) {
34401
34411
if (!isValidConstAssertionArgument(expression)) {
34402
34412
error(expression, Diagnostics.A_const_assertions_can_only_be_applied_to_references_to_enum_members_or_string_number_boolean_array_or_object_literals);
34403
34413
}
34404
34414
return getRegularTypeOfLiteralType(exprType);
34405
34415
}
34406
34416
checkSourceElement(type);
34407
- exprType = getRegularTypeOfObjectLiteral(getBaseTypeOfLiteralType(exprType));
34417
+ checkNodeDeferred(node);
34418
+ return getTypeFromTypeNode(type);
34419
+ }
34420
+
34421
+ function getAssertionTypeAndExpression(node: JSDocTypeAssertion | AssertionExpression) {
34422
+ let type: TypeNode;
34423
+ let expression: Expression;
34424
+ switch (node.kind) {
34425
+ case SyntaxKind.AsExpression:
34426
+ case SyntaxKind.TypeAssertionExpression:
34427
+ type = node.type;
34428
+ expression = node.expression;
34429
+ break;
34430
+ case SyntaxKind.ParenthesizedExpression:
34431
+ type = getJSDocTypeAssertionType(node);
34432
+ expression = node.expression;
34433
+ break;
34434
+ }
34435
+
34436
+ return { type, expression };
34437
+ }
34438
+
34439
+ function checkAssertionDeferred(node: JSDocTypeAssertion | AssertionExpression) {
34440
+ const { type, expression } = getAssertionTypeAndExpression(node);
34441
+ const errNode = isParenthesizedExpression(node) ? type : node;
34442
+ const exprType = getRegularTypeOfObjectLiteral(getBaseTypeOfLiteralType(checkExpression(expression)));
34408
34443
const targetType = getTypeFromTypeNode(type);
34409
34444
if (!isErrorType(targetType)) {
34410
34445
addLazyDiagnostic(() => {
@@ -34415,7 +34450,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
34415
34450
}
34416
34451
});
34417
34452
}
34418
- return targetType;
34419
34453
}
34420
34454
34421
34455
function checkNonNullChain(node: NonNullChain) {
@@ -34690,12 +34724,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
34690
34724
return undefined;
34691
34725
}
34692
34726
34693
- function getRestTypeAtPosition(source: Signature, pos: number, readonly = false ): Type {
34727
+ function getRestTypeAtPosition(source: Signature, pos: number): Type {
34694
34728
const parameterCount = getParameterCount(source);
34695
34729
const minArgumentCount = getMinArgumentCount(source);
34696
34730
const restType = getEffectiveRestType(source);
34697
34731
if (restType && pos >= parameterCount - 1) {
34698
- return pos === parameterCount - 1 ? restType : createArrayType(getIndexedAccessType(restType, numberType), readonly );
34732
+ return pos === parameterCount - 1 ? restType : createArrayType(getIndexedAccessType(restType, numberType));
34699
34733
}
34700
34734
const types = [];
34701
34735
const flags = [];
@@ -34714,7 +34748,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
34714
34748
names.push(name);
34715
34749
}
34716
34750
}
34717
- return createTupleType(types, flags, readonly, length(names) === length(types) ? names : undefined);
34751
+ return createTupleType(types, flags, /* readonly*/ false , length(names) === length(types) ? names : undefined);
34718
34752
}
34719
34753
34720
34754
// Return the number of parameters in a signature. The rest parameter, if present, counts as one
@@ -37661,8 +37695,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
37661
37695
return checkSatisfiesExpressionWorker(node.expression, getJSDocSatisfiesExpressionType(node), checkMode);
37662
37696
}
37663
37697
if (isJSDocTypeAssertion(node)) {
37664
- const type = getJSDocTypeAssertionType(node);
37665
- return checkAssertionWorker(type, type, node.expression, checkMode);
37698
+ return checkAssertionWorker(node, checkMode);
37666
37699
}
37667
37700
}
37668
37701
return checkExpression(node.expression, checkMode);
@@ -37743,7 +37776,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
37743
37776
return checkTypeOfExpression(node as TypeOfExpression);
37744
37777
case SyntaxKind.TypeAssertionExpression:
37745
37778
case SyntaxKind.AsExpression:
37746
- return checkAssertion(node as AssertionExpression);
37779
+ return checkAssertion(node as AssertionExpression, checkMode );
37747
37780
case SyntaxKind.NonNullExpression:
37748
37781
return checkNonNullAssertion(node as NonNullExpression);
37749
37782
case SyntaxKind.ExpressionWithTypeArguments:
@@ -44847,6 +44880,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
44847
44880
case SyntaxKind.JsxElement:
44848
44881
checkJsxElementDeferred(node as JsxElement);
44849
44882
break;
44883
+ case SyntaxKind.TypeAssertionExpression:
44884
+ case SyntaxKind.AsExpression:
44885
+ case SyntaxKind.ParenthesizedExpression:
44886
+ checkAssertionDeferred(node as AssertionExpression | JSDocTypeAssertion);
44850
44887
}
44851
44888
currentNode = saveCurrentNode;
44852
44889
tracing?.pop();
@@ -45308,7 +45345,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
45308
45345
}
45309
45346
45310
45347
meaning |= SymbolFlags.Alias;
45311
- const entityNameSymbol = isEntityNameExpression(name) ? resolveEntityName(name, meaning) : undefined;
45348
+ const entityNameSymbol = isEntityNameExpression(name) ? resolveEntityName(name, meaning, /*ignoreErrors*/ true ) : undefined;
45312
45349
if (entityNameSymbol) {
45313
45350
return entityNameSymbol;
45314
45351
}
0 commit comments