@@ -8402,12 +8402,12 @@ namespace ts {
8402
8402
}
8403
8403
8404
8404
function isNullOrUndefined(node: Expression) {
8405
- const expr = skipParentheses(node);
8405
+ const expr = skipParentheses(node, /*excludeJSDocTypeAssertions*/ true );
8406
8406
return expr.kind === SyntaxKind.NullKeyword || expr.kind === SyntaxKind.Identifier && getResolvedSymbol(expr as Identifier) === undefinedSymbol;
8407
8407
}
8408
8408
8409
8409
function isEmptyArrayLiteral(node: Expression) {
8410
- const expr = skipParentheses(node);
8410
+ const expr = skipParentheses(node, /*excludeJSDocTypeAssertions*/ true );
8411
8411
return expr.kind === SyntaxKind.ArrayLiteralExpression && (expr as ArrayLiteralExpression).elements.length === 0;
8412
8412
}
8413
8413
@@ -11800,7 +11800,7 @@ namespace ts {
11800
11800
// Flags we want to propagate to the result if they exist in all source symbols
11801
11801
let optionalFlag = isUnion ? SymbolFlags.None : SymbolFlags.Optional;
11802
11802
let syntheticFlag = CheckFlags.SyntheticMethod;
11803
- let checkFlags = 0 ;
11803
+ let checkFlags = isUnion ? 0 : CheckFlags.Readonly ;
11804
11804
let mergedInstantiations = false;
11805
11805
for (const current of containingType.types) {
11806
11806
const type = getApparentType(current);
@@ -11839,8 +11839,13 @@ namespace ts {
11839
11839
}
11840
11840
}
11841
11841
}
11842
- checkFlags |= (isReadonlySymbol(prop) ? CheckFlags.Readonly : 0) |
11843
- (!(modifiers & ModifierFlags.NonPublicAccessibilityModifier) ? CheckFlags.ContainsPublic : 0) |
11842
+ if (isUnion && isReadonlySymbol(prop)) {
11843
+ checkFlags |= CheckFlags.Readonly;
11844
+ }
11845
+ else if (!isUnion && !isReadonlySymbol(prop)) {
11846
+ checkFlags &= ~CheckFlags.Readonly;
11847
+ }
11848
+ checkFlags |= (!(modifiers & ModifierFlags.NonPublicAccessibilityModifier) ? CheckFlags.ContainsPublic : 0) |
11844
11849
(modifiers & ModifierFlags.Protected ? CheckFlags.ContainsProtected : 0) |
11845
11850
(modifiers & ModifierFlags.Private ? CheckFlags.ContainsPrivate : 0) |
11846
11851
(modifiers & ModifierFlags.Static ? CheckFlags.ContainsStatic : 0);
@@ -22966,7 +22971,7 @@ namespace ts {
22966
22971
}
22967
22972
22968
22973
function isFalseExpression(expr: Expression): boolean {
22969
- const node = skipParentheses(expr);
22974
+ const node = skipParentheses(expr, /*excludeJSDocTypeAssertions*/ true );
22970
22975
return node.kind === SyntaxKind.FalseKeyword || node.kind === SyntaxKind.BinaryExpression && (
22971
22976
(node as BinaryExpression).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken && (isFalseExpression((node as BinaryExpression).left) || isFalseExpression((node as BinaryExpression).right)) ||
22972
22977
(node as BinaryExpression).operatorToken.kind === SyntaxKind.BarBarToken && isFalseExpression((node as BinaryExpression).left) && isFalseExpression((node as BinaryExpression).right));
@@ -23288,7 +23293,7 @@ namespace ts {
23288
23293
}
23289
23294
23290
23295
function narrowTypeByAssertion(type: Type, expr: Expression): Type {
23291
- const node = skipParentheses(expr);
23296
+ const node = skipParentheses(expr, /*excludeJSDocTypeAssertions*/ true );
23292
23297
if (node.kind === SyntaxKind.FalseKeyword) {
23293
23298
return unreachableNeverType;
23294
23299
}
@@ -25872,7 +25877,9 @@ namespace ts {
25872
25877
case SyntaxKind.ParenthesizedExpression: {
25873
25878
// Like in `checkParenthesizedExpression`, an `/** @type {xyz} */` comment before a parenthesized expression acts as a type cast.
25874
25879
const tag = isInJSFile(parent) ? getJSDocTypeTag(parent) : undefined;
25875
- return tag ? getTypeFromTypeNode(tag.typeExpression.type) : getContextualType(parent as ParenthesizedExpression, contextFlags);
25880
+ return !tag ? getContextualType(parent as ParenthesizedExpression, contextFlags) :
25881
+ isJSDocTypeTag(tag) && isConstTypeReference(tag.typeExpression.type) ? tryFindWhenConstTypeReference(parent as ParenthesizedExpression) :
25882
+ getTypeFromTypeNode(tag.typeExpression.type);
25876
25883
}
25877
25884
case SyntaxKind.NonNullExpression:
25878
25885
return getContextualType(parent as NonNullExpression, contextFlags);
@@ -32855,8 +32862,10 @@ namespace ts {
32855
32862
}
32856
32863
32857
32864
function isTypeAssertion(node: Expression) {
32858
- node = skipParentheses(node);
32859
- return node.kind === SyntaxKind.TypeAssertionExpression || node.kind === SyntaxKind.AsExpression;
32865
+ node = skipParentheses(node, /*excludeJSDocTypeAssertions*/ true);
32866
+ return node.kind === SyntaxKind.TypeAssertionExpression ||
32867
+ node.kind === SyntaxKind.AsExpression ||
32868
+ isJSDocTypeAssertion(node);
32860
32869
}
32861
32870
32862
32871
function checkDeclarationInitializer(declaration: HasExpressionInitializer, contextualType?: Type | undefined) {
@@ -32931,6 +32940,7 @@ namespace ts {
32931
32940
function isConstContext(node: Expression): boolean {
32932
32941
const parent = node.parent;
32933
32942
return isAssertionExpression(parent) && isConstTypeReference(parent.type) ||
32943
+ isJSDocTypeAssertion(parent) && isConstTypeReference(getJSDocTypeAssertionType(parent)) ||
32934
32944
(isParenthesizedExpression(parent) || isArrayLiteralExpression(parent) || isSpreadElement(parent)) && isConstContext(parent) ||
32935
32945
(isPropertyAssignment(parent) || isShorthandPropertyAssignment(parent) || isTemplateSpan(parent)) && isConstContext(parent.parent);
32936
32946
}
@@ -33143,7 +33153,14 @@ namespace ts {
33143
33153
}
33144
33154
33145
33155
function getQuickTypeOfExpression(node: Expression) {
33146
- const expr = skipParentheses(node);
33156
+ let expr = skipParentheses(node, /*excludeJSDocTypeAssertions*/ true);
33157
+ if (isJSDocTypeAssertion(expr)) {
33158
+ const type = getJSDocTypeAssertionType(expr);
33159
+ if (!isConstTypeReference(type)) {
33160
+ return getTypeFromTypeNode(type);
33161
+ }
33162
+ }
33163
+ expr = skipParentheses(node);
33147
33164
// Optimize for the common case of a call to a function with a single non-generic call
33148
33165
// signature where we can just fetch the return type without checking the arguments.
33149
33166
if (isCallExpression(expr) && expr.expression.kind !== SyntaxKind.SuperKeyword && !isRequireCall(expr, /*checkArgumentIsStringLiteralLike*/ true) && !isSymbolOrSymbolForCall(expr)) {
@@ -33230,9 +33247,9 @@ namespace ts {
33230
33247
}
33231
33248
33232
33249
function checkParenthesizedExpression(node: ParenthesizedExpression, checkMode?: CheckMode): Type {
33233
- const tag = isInJSFile(node) ? getJSDocTypeTag (node) : undefined;
33234
- if (tag) {
33235
- return checkAssertionWorker(tag.typeExpression. type, tag.typeExpression. type, node.expression, checkMode);
33250
+ if (isJSDocTypeAssertion (node)) {
33251
+ const type = getJSDocTypeAssertionType(node);
33252
+ return checkAssertionWorker(type, type, node.expression, checkMode);
33236
33253
}
33237
33254
return checkExpression(node.expression, checkMode);
33238
33255
}
@@ -36182,7 +36199,7 @@ namespace ts {
36182
36199
if (getFalsyFlags(type)) return;
36183
36200
36184
36201
const location = isBinaryExpression(condExpr) ? condExpr.right : condExpr;
36185
- if (isPropertyAccessExpression(location) && isAssertionExpression(skipParentheses( location.expression) )) {
36202
+ if (isPropertyAccessExpression(location) && isTypeAssertion( location.expression)) {
36186
36203
return;
36187
36204
}
36188
36205
0 commit comments