@@ -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 |
|
|