mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Treat '!' differently inside chain vs end of chain
This commit is contained in:
+20
-4
@@ -833,6 +833,9 @@ namespace ts {
|
||||
case SyntaxKind.CallExpression:
|
||||
bindCallExpressionFlow(<CallExpression>node);
|
||||
break;
|
||||
case SyntaxKind.NonNullExpression:
|
||||
bindNonNullExpressionFlow(<NonNullExpression>node);
|
||||
break;
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
case SyntaxKind.JSDocEnumTag:
|
||||
@@ -1665,18 +1668,22 @@ namespace ts {
|
||||
}
|
||||
|
||||
function bindOptionalChainRest(node: OptionalChain) {
|
||||
bind(node.questionDotToken);
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
bind(node.questionDotToken);
|
||||
bind(node.name);
|
||||
break;
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
bind(node.questionDotToken);
|
||||
bind(node.argumentExpression);
|
||||
break;
|
||||
case SyntaxKind.CallExpression:
|
||||
bind(node.questionDotToken);
|
||||
bindEach(node.typeArguments);
|
||||
bindEach(node.arguments);
|
||||
break;
|
||||
case SyntaxKind.NonNullExpression:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1692,7 +1699,7 @@ namespace ts {
|
||||
// and build it's CFA graph as if it were the first condition (`a && ...`). Then we bind the rest
|
||||
// of the node as part of the "true" branch, and continue to do so as we ascend back up to the outermost
|
||||
// chain node. We then treat the entire node as the right side of the expression.
|
||||
const preChainLabel = node.questionDotToken ? createBranchLabel() : undefined;
|
||||
const preChainLabel = isOptionalChainRoot(node) ? createBranchLabel() : undefined;
|
||||
bindOptionalExpression(node.expression, preChainLabel || trueTarget, falseTarget);
|
||||
if (preChainLabel) {
|
||||
currentFlow = finishFlowLabel(preChainLabel);
|
||||
@@ -1715,7 +1722,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function bindAccessExpressionFlow(node: AccessExpression) {
|
||||
function bindNonNullExpressionFlow(node: NonNullExpression | NonNullChain) {
|
||||
if (isOptionalChain(node)) {
|
||||
bindOptionalChainFlow(node);
|
||||
}
|
||||
@@ -1724,7 +1731,16 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function bindCallExpressionFlow(node: CallExpression) {
|
||||
function bindAccessExpressionFlow(node: AccessExpression | PropertyAccessChain | ElementAccessChain) {
|
||||
if (isOptionalChain(node)) {
|
||||
bindOptionalChainFlow(node);
|
||||
}
|
||||
else {
|
||||
bindEachChild(node);
|
||||
}
|
||||
}
|
||||
|
||||
function bindCallExpressionFlow(node: CallExpression | CallChain) {
|
||||
if (isOptionalChain(node)) {
|
||||
bindOptionalChainFlow(node);
|
||||
}
|
||||
|
||||
@@ -25900,8 +25900,15 @@ namespace ts {
|
||||
return targetType;
|
||||
}
|
||||
|
||||
function checkNonNullChain(node: NonNullChain) {
|
||||
const leftType = checkExpression(node.expression);
|
||||
const nonOptionalType = getOptionalExpressionType(leftType, node.expression);
|
||||
return propagateOptionalTypeMarker(getNonNullableType(nonOptionalType), node, nonOptionalType !== leftType);
|
||||
}
|
||||
|
||||
function checkNonNullAssertion(node: NonNullExpression) {
|
||||
return getNonNullableType(checkExpression(node.expression));
|
||||
return node.flags & NodeFlags.OptionalChain ? checkNonNullChain(node as NonNullChain) :
|
||||
getNonNullableType(checkExpression(node.expression));
|
||||
}
|
||||
|
||||
function checkMetaProperty(node: MetaProperty): Type {
|
||||
|
||||
+11
-7
@@ -189,13 +189,17 @@ namespace ts {
|
||||
assertNode)
|
||||
: noop;
|
||||
|
||||
export const assertNotNode = shouldAssert(AssertionLevel.Normal)
|
||||
? (node: Node | undefined, test: ((node: Node | undefined) => boolean) | undefined, message?: string): void => assert(
|
||||
test === undefined || !test(node),
|
||||
message || "Unexpected node.",
|
||||
() => `Node ${formatSyntaxKind(node!.kind)} should not have passed test '${getFunctionName(test!)}'.`,
|
||||
assertNode)
|
||||
: noop;
|
||||
export function assertNotNode<T extends Node, U extends T>(node: T | undefined, test: (node: Node) => node is U, message?: string): asserts node is Exclude<T, U>;
|
||||
export function assertNotNode(node: Node | undefined, test: ((node: Node) => boolean) | undefined, message?: string): void;
|
||||
export function assertNotNode(node: Node | undefined, test: ((node: Node) => boolean) | undefined, message?: string): void {
|
||||
if (shouldAssert(AssertionLevel.Normal)) {
|
||||
assert(
|
||||
test === undefined || node === undefined || !test(node),
|
||||
message || "Unexpected node.",
|
||||
() => `Node ${formatSyntaxKind(node!.kind)} should not have passed test '${getFunctionName(test!)}'.`,
|
||||
assertNotNode);
|
||||
}
|
||||
}
|
||||
|
||||
export const assertOptionalNode = shouldAssert(AssertionLevel.Normal)
|
||||
? (node: Node, test: (node: Node) => boolean, message?: string): void => assert(
|
||||
|
||||
+9
-24
@@ -1335,9 +1335,11 @@ namespace ts {
|
||||
|
||||
export const enum OuterExpressionKinds {
|
||||
Parentheses = 1 << 0,
|
||||
Assertions = 1 << 1,
|
||||
PartiallyEmittedExpressions = 1 << 2,
|
||||
TypeAssertions = 1 << 1,
|
||||
NonNullAssertions = 1 << 2,
|
||||
PartiallyEmittedExpressions = 1 << 3,
|
||||
|
||||
Assertions = TypeAssertions | NonNullAssertions,
|
||||
All = Parentheses | Assertions | PartiallyEmittedExpressions
|
||||
}
|
||||
|
||||
@@ -1349,8 +1351,9 @@ namespace ts {
|
||||
return (kinds & OuterExpressionKinds.Parentheses) !== 0;
|
||||
case SyntaxKind.TypeAssertionExpression:
|
||||
case SyntaxKind.AsExpression:
|
||||
return (kinds & OuterExpressionKinds.TypeAssertions) !== 0;
|
||||
case SyntaxKind.NonNullExpression:
|
||||
return (kinds & OuterExpressionKinds.Assertions) !== 0;
|
||||
return (kinds & OuterExpressionKinds.NonNullAssertions) !== 0;
|
||||
case SyntaxKind.PartiallyEmittedExpression:
|
||||
return (kinds & OuterExpressionKinds.PartiallyEmittedExpressions) !== 0;
|
||||
}
|
||||
@@ -1360,34 +1363,16 @@ namespace ts {
|
||||
export function skipOuterExpressions(node: Expression, kinds?: OuterExpressionKinds): Expression;
|
||||
export function skipOuterExpressions(node: Node, kinds?: OuterExpressionKinds): Node;
|
||||
export function skipOuterExpressions(node: Node, kinds = OuterExpressionKinds.All) {
|
||||
let previousNode: Node;
|
||||
do {
|
||||
previousNode = node;
|
||||
if (kinds & OuterExpressionKinds.Parentheses) {
|
||||
node = skipParentheses(node);
|
||||
}
|
||||
|
||||
if (kinds & OuterExpressionKinds.Assertions) {
|
||||
node = skipAssertions(node);
|
||||
}
|
||||
|
||||
if (kinds & OuterExpressionKinds.PartiallyEmittedExpressions) {
|
||||
node = skipPartiallyEmittedExpressions(node);
|
||||
}
|
||||
while (isOuterExpression(node, kinds)) {
|
||||
node = node.expression;
|
||||
}
|
||||
while (previousNode !== node);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
export function skipAssertions(node: Expression): Expression;
|
||||
export function skipAssertions(node: Node): Node;
|
||||
export function skipAssertions(node: Node): Node {
|
||||
while (isAssertionExpression(node) || node.kind === SyntaxKind.NonNullExpression) {
|
||||
node = (<AssertionExpression | NonNullExpression>node).expression;
|
||||
}
|
||||
|
||||
return node;
|
||||
return skipOuterExpressions(node, OuterExpressionKinds.Assertions);
|
||||
}
|
||||
|
||||
function updateOuterExpression(outerExpression: OuterExpression, expression: Expression) {
|
||||
|
||||
@@ -1076,10 +1076,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier | PrivateIdentifier) {
|
||||
if (isOptionalChain(node) && isIdentifier(node.name) && isIdentifier(name)) {
|
||||
// Not sure why this cast was necessary: the previous line should already establish that node.name is an identifier
|
||||
const theNode = node as (typeof node & { name: Identifier });
|
||||
return updatePropertyAccessChain(theNode, expression, node.questionDotToken, name);
|
||||
if (isPropertyAccessChain(node)) {
|
||||
return updatePropertyAccessChain(node, expression, node.questionDotToken, cast(name, isIdentifier));
|
||||
}
|
||||
// Because we are updating existed propertyAccess we want to inherit its emitFlags
|
||||
// instead of using the default from createPropertyAccess
|
||||
@@ -1653,11 +1651,28 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function updateNonNullExpression(node: NonNullExpression, expression: Expression) {
|
||||
if (isNonNullChain(node)) {
|
||||
return updateNonNullChain(node, expression);
|
||||
}
|
||||
return node.expression !== expression
|
||||
? updateNode(createNonNullExpression(expression), node)
|
||||
: node;
|
||||
}
|
||||
|
||||
export function createNonNullChain(expression: Expression) {
|
||||
const node = <NonNullChain>createSynthesizedNode(SyntaxKind.NonNullExpression);
|
||||
node.flags |= NodeFlags.OptionalChain;
|
||||
node.expression = parenthesizeForAccess(expression);
|
||||
return node;
|
||||
}
|
||||
|
||||
export function updateNonNullChain(node: NonNullChain, expression: Expression) {
|
||||
Debug.assert(!!(node.flags & NodeFlags.OptionalChain), "Cannot update a NonNullExpression using updateNonNullChain. Use updateNonNullExpression instead.");
|
||||
return node.expression !== expression
|
||||
? updateNode(createNonNullChain(expression), node)
|
||||
: node;
|
||||
}
|
||||
|
||||
export function createMetaProperty(keywordToken: MetaProperty["keywordToken"], name: Identifier) {
|
||||
const node = <MetaProperty>createSynthesizedNode(SyntaxKind.MetaProperty);
|
||||
node.keywordToken = keywordToken;
|
||||
|
||||
+23
-9
@@ -4685,12 +4685,26 @@ namespace ts {
|
||||
&& lookAhead(nextTokenIsIdentifierOrKeywordOrOpenBracketOrTemplate);
|
||||
}
|
||||
|
||||
function hasOptionalChain(node: Node) {
|
||||
while (true) {
|
||||
if (node.flags & NodeFlags.OptionalChain) return true;
|
||||
if (!isNonNullExpression(node)) return false;
|
||||
node = node.expression;
|
||||
function tryReparseOptionalChain(node: Expression) {
|
||||
if (node.flags & NodeFlags.OptionalChain) {
|
||||
return true;
|
||||
}
|
||||
// check for an optional chain in a non-null expression
|
||||
if (isNonNullExpression(node)) {
|
||||
let expr = node.expression;
|
||||
while (isNonNullExpression(expr) && !(expr.flags & NodeFlags.OptionalChain)) {
|
||||
expr = expr.expression;
|
||||
}
|
||||
if (expr.flags & NodeFlags.OptionalChain) {
|
||||
// this is part of an optional chain. Walk down from `node` to `expression` and set the flag.
|
||||
while (isNonNullExpression(node)) {
|
||||
node.flags |= NodeFlags.OptionalChain;
|
||||
node = node.expression;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function parsePropertyAccessExpressionRest(expression: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined) {
|
||||
@@ -4698,7 +4712,7 @@ namespace ts {
|
||||
propertyAccess.expression = expression;
|
||||
propertyAccess.questionDotToken = questionDotToken;
|
||||
propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ true);
|
||||
if (questionDotToken || hasOptionalChain(expression)) {
|
||||
if (questionDotToken || tryReparseOptionalChain(expression)) {
|
||||
propertyAccess.flags |= NodeFlags.OptionalChain;
|
||||
if (isPrivateIdentifier(propertyAccess.name)) {
|
||||
parseErrorAtRange(propertyAccess.name, Diagnostics.An_optional_chain_cannot_contain_private_identifiers);
|
||||
@@ -4724,7 +4738,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
parseExpected(SyntaxKind.CloseBracketToken);
|
||||
if (questionDotToken || hasOptionalChain(expression)) {
|
||||
if (questionDotToken || tryReparseOptionalChain(expression)) {
|
||||
indexedAccess.flags |= NodeFlags.OptionalChain;
|
||||
}
|
||||
return finishNode(indexedAccess);
|
||||
@@ -4811,7 +4825,7 @@ namespace ts {
|
||||
callExpr.questionDotToken = questionDotToken;
|
||||
callExpr.typeArguments = typeArguments;
|
||||
callExpr.arguments = parseArgumentList();
|
||||
if (questionDotToken || hasOptionalChain(expression)) {
|
||||
if (questionDotToken || tryReparseOptionalChain(expression)) {
|
||||
callExpr.flags |= NodeFlags.OptionalChain;
|
||||
}
|
||||
expression = finishNode(callExpr);
|
||||
@@ -4823,7 +4837,7 @@ namespace ts {
|
||||
callExpr.expression = expression;
|
||||
callExpr.questionDotToken = questionDotToken;
|
||||
callExpr.arguments = parseArgumentList();
|
||||
if (questionDotToken || hasOptionalChain(expression)) {
|
||||
if (questionDotToken || tryReparseOptionalChain(expression)) {
|
||||
callExpr.flags |= NodeFlags.OptionalChain;
|
||||
}
|
||||
expression = finishNode(callExpr);
|
||||
|
||||
@@ -42,9 +42,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function flattenChain(chain: OptionalChain) {
|
||||
Debug.assertNotNode(chain, isNonNullChain);
|
||||
const links: OptionalChain[] = [chain];
|
||||
while (!chain.questionDotToken && !isTaggedTemplateExpression(chain)) {
|
||||
chain = cast(skipPartiallyEmittedExpressions(chain.expression), isOptionalChain);
|
||||
Debug.assertNotNode(chain, isNonNullChain);
|
||||
links.unshift(chain);
|
||||
}
|
||||
return { expression: chain.expression, chain: links };
|
||||
|
||||
@@ -1922,6 +1922,7 @@ namespace ts {
|
||||
| PropertyAccessChain
|
||||
| ElementAccessChain
|
||||
| CallChain
|
||||
| NonNullChain
|
||||
;
|
||||
|
||||
/* @internal */
|
||||
@@ -2016,6 +2017,10 @@ namespace ts {
|
||||
expression: Expression;
|
||||
}
|
||||
|
||||
export interface NonNullChain extends NonNullExpression {
|
||||
_optionalChainBrand: any;
|
||||
}
|
||||
|
||||
// NOTE: MetaProperty is really a MemberExpression, but we consider it a PrimaryExpression
|
||||
// for the same reasons we treat NewExpression as a PrimaryExpression.
|
||||
export interface MetaProperty extends PrimaryExpression {
|
||||
|
||||
@@ -2614,11 +2614,7 @@ namespace ts {
|
||||
export function skipParentheses(node: Expression): Expression;
|
||||
export function skipParentheses(node: Node): Node;
|
||||
export function skipParentheses(node: Node): Node {
|
||||
while (node.kind === SyntaxKind.ParenthesizedExpression) {
|
||||
node = (node as ParenthesizedExpression).expression;
|
||||
}
|
||||
|
||||
return node;
|
||||
return skipOuterExpressions(node, OuterExpressionKinds.Parentheses);
|
||||
}
|
||||
|
||||
function skipParenthesesUp(node: Node): Node {
|
||||
|
||||
@@ -1076,17 +1076,18 @@ namespace ts {
|
||||
return isCallExpression(node) && !!(node.flags & NodeFlags.OptionalChain);
|
||||
}
|
||||
|
||||
export function isOptionalChain(node: Node): node is PropertyAccessChain | ElementAccessChain | CallChain {
|
||||
export function isOptionalChain(node: Node): node is PropertyAccessChain | ElementAccessChain | CallChain | NonNullChain {
|
||||
const kind = node.kind;
|
||||
return !!(node.flags & NodeFlags.OptionalChain) &&
|
||||
(kind === SyntaxKind.PropertyAccessExpression
|
||||
|| kind === SyntaxKind.ElementAccessExpression
|
||||
|| kind === SyntaxKind.CallExpression);
|
||||
|| kind === SyntaxKind.CallExpression
|
||||
|| kind === SyntaxKind.NonNullExpression);
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function isOptionalChainRoot(node: Node): node is OptionalChainRoot {
|
||||
return isOptionalChain(node) && !!node.questionDotToken;
|
||||
return isOptionalChain(node) && !isNonNullExpression(node) && !!node.questionDotToken;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1101,17 +1102,18 @@ namespace ts {
|
||||
* Determines whether a node is the outermost `OptionalChain` in an ECMAScript `OptionalExpression`:
|
||||
*
|
||||
* 1. For `a?.b.c`, the outermost chain is `a?.b.c` (`c` is the end of the chain starting at `a?.`)
|
||||
* 2. For `(a?.b.c).d`, the outermost chain is `a?.b.c` (`c` is the end of the chain starting at `a?.` since parens end the chain)
|
||||
* 3. For `a?.b.c?.d`, both `a?.b.c` and `a?.b.c?.d` are outermost (`c` is the end of the chain starting at `a?.`, and `d` is
|
||||
* 2. For `a?.b!`, the outermost chain is `a?.b!` (`c` is the end of the chain starting at `a?.`)
|
||||
* 3. For `(a?.b.c).d`, the outermost chain is `a?.b.c` (`c` is the end of the chain starting at `a?.` since parens end the chain)
|
||||
* 4. For `a?.b.c?.d`, both `a?.b.c` and `a?.b.c?.d` are outermost (`c` is the end of the chain starting at `a?.`, and `d` is
|
||||
* the end of the chain starting at `c?.`)
|
||||
* 4. For `a?.(b?.c).d`, both `b?.c` and `a?.(b?.c)d` are outermost (`c` is the end of the chain starting at `b`, and `d` is
|
||||
* 5. For `a?.(b?.c).d`, both `b?.c` and `a?.(b?.c)d` are outermost (`c` is the end of the chain starting at `b`, and `d` is
|
||||
* the end of the chain starting at `a?.`)
|
||||
*/
|
||||
/* @internal */
|
||||
export function isOutermostOptionalChain(node: OptionalChain) {
|
||||
return !isOptionalChain(node.parent) // cases 1 and 2
|
||||
|| isOptionalChainRoot(node.parent) // case 3
|
||||
|| node !== node.parent.expression; // case 4
|
||||
return !isOptionalChain(node.parent) // cases 1, 2, and 3
|
||||
|| isOptionalChainRoot(node.parent) // case 4
|
||||
|| node !== node.parent.expression; // case 5
|
||||
}
|
||||
|
||||
export function isNullishCoalesce(node: Node) {
|
||||
@@ -1142,11 +1144,7 @@ namespace ts {
|
||||
export function skipPartiallyEmittedExpressions(node: Expression): Expression;
|
||||
export function skipPartiallyEmittedExpressions(node: Node): Node;
|
||||
export function skipPartiallyEmittedExpressions(node: Node) {
|
||||
while (node.kind === SyntaxKind.PartiallyEmittedExpression) {
|
||||
node = (<PartiallyEmittedExpression>node).expression;
|
||||
}
|
||||
|
||||
return node;
|
||||
return skipOuterExpressions(node, OuterExpressionKinds.PartiallyEmittedExpressions);
|
||||
}
|
||||
|
||||
export function isFunctionExpression(node: Node): node is FunctionExpression {
|
||||
@@ -1221,6 +1219,10 @@ namespace ts {
|
||||
return node.kind === SyntaxKind.NonNullExpression;
|
||||
}
|
||||
|
||||
export function isNonNullChain(node: Node): node is NonNullChain {
|
||||
return isNonNullExpression(node) && !!(node.flags & NodeFlags.OptionalChain);
|
||||
}
|
||||
|
||||
export function isMetaProperty(node: Node): node is MetaProperty {
|
||||
return node.kind === SyntaxKind.MetaProperty;
|
||||
}
|
||||
|
||||
@@ -1012,7 +1012,7 @@ namespace ts {
|
||||
export function getPossibleGenericSignatures(called: Expression, typeArgumentCount: number, checker: TypeChecker): readonly Signature[] {
|
||||
let type = checker.getTypeAtLocation(called);
|
||||
if (isOptionalChain(called.parent)) {
|
||||
type = removeOptionality(type, !!called.parent.questionDotToken, /*isOptionalChain*/ true);
|
||||
type = removeOptionality(type, isOptionalChainRoot(called.parent), /*isOptionalChain*/ true);
|
||||
}
|
||||
|
||||
const signatures = isNewExpression(called.parent) ? type.getConstructSignatures() : type.getCallSignatures();
|
||||
|
||||
+8
-2
@@ -1136,7 +1136,7 @@ declare namespace ts {
|
||||
export interface CallChain extends CallExpression {
|
||||
_optionalChainBrand: any;
|
||||
}
|
||||
export type OptionalChain = PropertyAccessChain | ElementAccessChain | CallChain;
|
||||
export type OptionalChain = PropertyAccessChain | ElementAccessChain | CallChain | NonNullChain;
|
||||
export interface SuperCall extends CallExpression {
|
||||
expression: SuperExpression;
|
||||
}
|
||||
@@ -1176,6 +1176,9 @@ declare namespace ts {
|
||||
kind: SyntaxKind.NonNullExpression;
|
||||
expression: Expression;
|
||||
}
|
||||
export interface NonNullChain extends NonNullExpression {
|
||||
_optionalChainBrand: any;
|
||||
}
|
||||
export interface MetaProperty extends PrimaryExpression {
|
||||
kind: SyntaxKind.MetaProperty;
|
||||
keywordToken: SyntaxKind.NewKeyword | SyntaxKind.ImportKeyword;
|
||||
@@ -3615,7 +3618,7 @@ declare namespace ts {
|
||||
function isElementAccessChain(node: Node): node is ElementAccessChain;
|
||||
function isCallExpression(node: Node): node is CallExpression;
|
||||
function isCallChain(node: Node): node is CallChain;
|
||||
function isOptionalChain(node: Node): node is PropertyAccessChain | ElementAccessChain | CallChain;
|
||||
function isOptionalChain(node: Node): node is PropertyAccessChain | ElementAccessChain | CallChain | NonNullChain;
|
||||
function isNullishCoalesce(node: Node): boolean;
|
||||
function isNewExpression(node: Node): node is NewExpression;
|
||||
function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression;
|
||||
@@ -3642,6 +3645,7 @@ declare namespace ts {
|
||||
function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments;
|
||||
function isAsExpression(node: Node): node is AsExpression;
|
||||
function isNonNullExpression(node: Node): node is NonNullExpression;
|
||||
function isNonNullChain(node: Node): node is NonNullChain;
|
||||
function isMetaProperty(node: Node): node is MetaProperty;
|
||||
function isTemplateSpan(node: Node): node is TemplateSpan;
|
||||
function isSemicolonClassElement(node: Node): node is SemicolonClassElement;
|
||||
@@ -4130,6 +4134,8 @@ declare namespace ts {
|
||||
function updateAsExpression(node: AsExpression, expression: Expression, type: TypeNode): AsExpression;
|
||||
function createNonNullExpression(expression: Expression): NonNullExpression;
|
||||
function updateNonNullExpression(node: NonNullExpression, expression: Expression): NonNullExpression;
|
||||
function createNonNullChain(expression: Expression): NonNullChain;
|
||||
function updateNonNullChain(node: NonNullChain, expression: Expression): NonNullChain;
|
||||
function createMetaProperty(keywordToken: MetaProperty["keywordToken"], name: Identifier): MetaProperty;
|
||||
function updateMetaProperty(node: MetaProperty, name: Identifier): MetaProperty;
|
||||
function createTemplateSpan(expression: Expression, literal: TemplateMiddle | TemplateTail): TemplateSpan;
|
||||
|
||||
+8
-2
@@ -1136,7 +1136,7 @@ declare namespace ts {
|
||||
export interface CallChain extends CallExpression {
|
||||
_optionalChainBrand: any;
|
||||
}
|
||||
export type OptionalChain = PropertyAccessChain | ElementAccessChain | CallChain;
|
||||
export type OptionalChain = PropertyAccessChain | ElementAccessChain | CallChain | NonNullChain;
|
||||
export interface SuperCall extends CallExpression {
|
||||
expression: SuperExpression;
|
||||
}
|
||||
@@ -1176,6 +1176,9 @@ declare namespace ts {
|
||||
kind: SyntaxKind.NonNullExpression;
|
||||
expression: Expression;
|
||||
}
|
||||
export interface NonNullChain extends NonNullExpression {
|
||||
_optionalChainBrand: any;
|
||||
}
|
||||
export interface MetaProperty extends PrimaryExpression {
|
||||
kind: SyntaxKind.MetaProperty;
|
||||
keywordToken: SyntaxKind.NewKeyword | SyntaxKind.ImportKeyword;
|
||||
@@ -3615,7 +3618,7 @@ declare namespace ts {
|
||||
function isElementAccessChain(node: Node): node is ElementAccessChain;
|
||||
function isCallExpression(node: Node): node is CallExpression;
|
||||
function isCallChain(node: Node): node is CallChain;
|
||||
function isOptionalChain(node: Node): node is PropertyAccessChain | ElementAccessChain | CallChain;
|
||||
function isOptionalChain(node: Node): node is PropertyAccessChain | ElementAccessChain | CallChain | NonNullChain;
|
||||
function isNullishCoalesce(node: Node): boolean;
|
||||
function isNewExpression(node: Node): node is NewExpression;
|
||||
function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression;
|
||||
@@ -3642,6 +3645,7 @@ declare namespace ts {
|
||||
function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments;
|
||||
function isAsExpression(node: Node): node is AsExpression;
|
||||
function isNonNullExpression(node: Node): node is NonNullExpression;
|
||||
function isNonNullChain(node: Node): node is NonNullChain;
|
||||
function isMetaProperty(node: Node): node is MetaProperty;
|
||||
function isTemplateSpan(node: Node): node is TemplateSpan;
|
||||
function isSemicolonClassElement(node: Node): node is SemicolonClassElement;
|
||||
@@ -4130,6 +4134,8 @@ declare namespace ts {
|
||||
function updateAsExpression(node: AsExpression, expression: Expression, type: TypeNode): AsExpression;
|
||||
function createNonNullExpression(expression: Expression): NonNullExpression;
|
||||
function updateNonNullExpression(node: NonNullExpression, expression: Expression): NonNullExpression;
|
||||
function createNonNullChain(expression: Expression): NonNullChain;
|
||||
function updateNonNullChain(node: NonNullChain, expression: Expression): NonNullChain;
|
||||
function createMetaProperty(keywordToken: MetaProperty["keywordToken"], name: Identifier): MetaProperty;
|
||||
function updateMetaProperty(node: MetaProperty, name: Identifier): MetaProperty;
|
||||
function createTemplateSpan(expression: Expression, literal: TemplateMiddle | TemplateTail): TemplateSpan;
|
||||
|
||||
@@ -38,7 +38,8 @@ declare const o5: <T>() => undefined | (() => void);
|
||||
o5<number>()?.();
|
||||
|
||||
// GH#36031
|
||||
o2?.b()!.toString
|
||||
o2?.b()!.toString;
|
||||
o2?.b()!.toString!;
|
||||
|
||||
//// [callChain.js]
|
||||
"use strict";
|
||||
@@ -78,3 +79,4 @@ var v = o4 === null || o4 === void 0 ? void 0 : o4(incr);
|
||||
(_o = o5()) === null || _o === void 0 ? void 0 : _o();
|
||||
// GH#36031
|
||||
o2 === null || o2 === void 0 ? void 0 : o2.b().toString;
|
||||
o2 === null || o2 === void 0 ? void 0 : o2.b().toString;
|
||||
|
||||
@@ -157,7 +157,14 @@ o5<number>()?.();
|
||||
>o5 : Symbol(o5, Decl(callChain.ts, 35, 13))
|
||||
|
||||
// GH#36031
|
||||
o2?.b()!.toString
|
||||
o2?.b()!.toString;
|
||||
>o2?.b()!.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
|
||||
>o2?.b : Symbol(b, Decl(callChain.ts, 6, 31))
|
||||
>o2 : Symbol(o2, Decl(callChain.ts, 6, 13))
|
||||
>b : Symbol(b, Decl(callChain.ts, 6, 31))
|
||||
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
o2?.b()!.toString!;
|
||||
>o2?.b()!.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
|
||||
>o2?.b : Symbol(b, Decl(callChain.ts, 6, 31))
|
||||
>o2 : Symbol(o2, Decl(callChain.ts, 6, 13))
|
||||
|
||||
@@ -265,12 +265,22 @@ o5<number>()?.();
|
||||
>o5 : <T>() => (() => void) | undefined
|
||||
|
||||
// GH#36031
|
||||
o2?.b()!.toString
|
||||
>o2?.b()!.toString : (radix?: number | undefined) => string
|
||||
>o2?.b()! : number
|
||||
o2?.b()!.toString;
|
||||
>o2?.b()!.toString : ((radix?: number | undefined) => string) | undefined
|
||||
>o2?.b()! : number | undefined
|
||||
>o2?.b() : number | undefined
|
||||
>o2?.b : ((...args: any[]) => number) | undefined
|
||||
>o2 : { b: (...args: any[]) => number; } | undefined
|
||||
>b : ((...args: any[]) => number) | undefined
|
||||
>toString : (radix?: number | undefined) => string
|
||||
>toString : ((radix?: number | undefined) => string) | undefined
|
||||
|
||||
o2?.b()!.toString!;
|
||||
>o2?.b()!.toString! : (radix?: number | undefined) => string
|
||||
>o2?.b()!.toString : ((radix?: number | undefined) => string) | undefined
|
||||
>o2?.b()! : number | undefined
|
||||
>o2?.b() : number | undefined
|
||||
>o2?.b : ((...args: any[]) => number) | undefined
|
||||
>o2 : { b: (...args: any[]) => number; } | undefined
|
||||
>b : ((...args: any[]) => number) | undefined
|
||||
>toString : ((radix?: number | undefined) => string) | undefined
|
||||
|
||||
|
||||
@@ -25,8 +25,10 @@ declare const o6: <T>() => undefined | ({ x: number });
|
||||
o6<number>()?.["x"];
|
||||
|
||||
// GH#36031
|
||||
o2?.["b"]!.c
|
||||
o2?.["b"]!["c"]
|
||||
o2?.["b"]!.c;
|
||||
o2?.["b"]!["c"];
|
||||
o2?.["b"]!.c!;
|
||||
o2?.["b"]!["c"]!;
|
||||
|
||||
//// [elementAccessChain.js]
|
||||
"use strict";
|
||||
@@ -46,3 +48,5 @@ o2 === null || o2 === void 0 ? void 0 : o2.b["c"];
|
||||
// GH#36031
|
||||
o2 === null || o2 === void 0 ? void 0 : o2["b"].c;
|
||||
o2 === null || o2 === void 0 ? void 0 : o2["b"]["c"];
|
||||
o2 === null || o2 === void 0 ? void 0 : o2["b"].c;
|
||||
o2 === null || o2 === void 0 ? void 0 : o2["b"]["c"];
|
||||
|
||||
@@ -107,12 +107,19 @@ o6<number>()?.["x"];
|
||||
>o6 : Symbol(o6, Decl(elementAccessChain.ts, 22, 13))
|
||||
|
||||
// GH#36031
|
||||
o2?.["b"]!.c
|
||||
o2?.["b"]!.c;
|
||||
>o2?.["b"]!.c : Symbol(c, Decl(elementAccessChain.ts, 3, 36))
|
||||
>o2 : Symbol(o2, Decl(elementAccessChain.ts, 3, 13))
|
||||
>c : Symbol(c, Decl(elementAccessChain.ts, 3, 36))
|
||||
|
||||
o2?.["b"]!["c"]
|
||||
o2?.["b"]!["c"];
|
||||
>o2 : Symbol(o2, Decl(elementAccessChain.ts, 3, 13))
|
||||
|
||||
o2?.["b"]!.c!;
|
||||
>o2?.["b"]!.c : Symbol(c, Decl(elementAccessChain.ts, 3, 36))
|
||||
>o2 : Symbol(o2, Decl(elementAccessChain.ts, 3, 13))
|
||||
>c : Symbol(c, Decl(elementAccessChain.ts, 3, 36))
|
||||
|
||||
o2?.["b"]!["c"]!;
|
||||
>o2 : Symbol(o2, Decl(elementAccessChain.ts, 3, 13))
|
||||
>"c" : Symbol(c, Decl(elementAccessChain.ts, 3, 36))
|
||||
|
||||
|
||||
@@ -142,17 +142,35 @@ o6<number>()?.["x"];
|
||||
>"x" : "x"
|
||||
|
||||
// GH#36031
|
||||
o2?.["b"]!.c
|
||||
>o2?.["b"]!.c : string
|
||||
>o2?.["b"]! : { c: string; }
|
||||
o2?.["b"]!.c;
|
||||
>o2?.["b"]!.c : string | undefined
|
||||
>o2?.["b"]! : { c: string; } | undefined
|
||||
>o2?.["b"] : { c: string; } | undefined
|
||||
>o2 : { b: { c: string; }; } | undefined
|
||||
>"b" : "b"
|
||||
>c : string
|
||||
>c : string | undefined
|
||||
|
||||
o2?.["b"]!["c"]
|
||||
>o2?.["b"]!["c"] : string
|
||||
>o2?.["b"]! : { c: string; }
|
||||
o2?.["b"]!["c"];
|
||||
>o2?.["b"]!["c"] : string | undefined
|
||||
>o2?.["b"]! : { c: string; } | undefined
|
||||
>o2?.["b"] : { c: string; } | undefined
|
||||
>o2 : { b: { c: string; }; } | undefined
|
||||
>"b" : "b"
|
||||
>"c" : "c"
|
||||
|
||||
o2?.["b"]!.c!;
|
||||
>o2?.["b"]!.c! : string
|
||||
>o2?.["b"]!.c : string | undefined
|
||||
>o2?.["b"]! : { c: string; } | undefined
|
||||
>o2?.["b"] : { c: string; } | undefined
|
||||
>o2 : { b: { c: string; }; } | undefined
|
||||
>"b" : "b"
|
||||
>c : string | undefined
|
||||
|
||||
o2?.["b"]!["c"]!;
|
||||
>o2?.["b"]!["c"]! : string
|
||||
>o2?.["b"]!["c"] : string | undefined
|
||||
>o2?.["b"]! : { c: string; } | undefined
|
||||
>o2?.["b"] : { c: string; } | undefined
|
||||
>o2 : { b: { c: string; }; } | undefined
|
||||
>"b" : "b"
|
||||
|
||||
@@ -22,7 +22,8 @@ o6<number>()?.x;
|
||||
o1?.b ? 1 : 0;
|
||||
|
||||
// GH#36031
|
||||
o2?.b!.c
|
||||
o2?.b!.c;
|
||||
o2?.b!.c!;
|
||||
|
||||
//// [propertyAccessChain.js]
|
||||
"use strict";
|
||||
@@ -37,3 +38,4 @@ o2 === null || o2 === void 0 ? void 0 : o2.b.c;
|
||||
(o1 === null || o1 === void 0 ? void 0 : o1.b) ? 1 : 0;
|
||||
// GH#36031
|
||||
o2 === null || o2 === void 0 ? void 0 : o2.b.c;
|
||||
o2 === null || o2 === void 0 ? void 0 : o2.b.c;
|
||||
|
||||
@@ -86,7 +86,14 @@ o1?.b ? 1 : 0;
|
||||
>b : Symbol(b, Decl(propertyAccessChain.ts, 0, 31))
|
||||
|
||||
// GH#36031
|
||||
o2?.b!.c
|
||||
o2?.b!.c;
|
||||
>o2?.b!.c : Symbol(c, Decl(propertyAccessChain.ts, 3, 36))
|
||||
>o2?.b : Symbol(b, Decl(propertyAccessChain.ts, 3, 31))
|
||||
>o2 : Symbol(o2, Decl(propertyAccessChain.ts, 3, 13))
|
||||
>b : Symbol(b, Decl(propertyAccessChain.ts, 3, 31))
|
||||
>c : Symbol(c, Decl(propertyAccessChain.ts, 3, 36))
|
||||
|
||||
o2?.b!.c!;
|
||||
>o2?.b!.c : Symbol(c, Decl(propertyAccessChain.ts, 3, 36))
|
||||
>o2?.b : Symbol(b, Decl(propertyAccessChain.ts, 3, 31))
|
||||
>o2 : Symbol(o2, Decl(propertyAccessChain.ts, 3, 13))
|
||||
|
||||
@@ -90,11 +90,20 @@ o1?.b ? 1 : 0;
|
||||
>0 : 0
|
||||
|
||||
// GH#36031
|
||||
o2?.b!.c
|
||||
>o2?.b!.c : string
|
||||
>o2?.b! : { c: string; }
|
||||
o2?.b!.c;
|
||||
>o2?.b!.c : string | undefined
|
||||
>o2?.b! : { c: string; } | undefined
|
||||
>o2?.b : { c: string; } | undefined
|
||||
>o2 : { b: { c: string; }; } | undefined
|
||||
>b : { c: string; } | undefined
|
||||
>c : string
|
||||
>c : string | undefined
|
||||
|
||||
o2?.b!.c!;
|
||||
>o2?.b!.c! : string
|
||||
>o2?.b!.c : string | undefined
|
||||
>o2?.b! : { c: string; } | undefined
|
||||
>o2?.b : { c: string; } | undefined
|
||||
>o2 : { b: { c: string; }; } | undefined
|
||||
>b : { c: string; } | undefined
|
||||
>c : string | undefined
|
||||
|
||||
|
||||
@@ -39,4 +39,5 @@ declare const o5: <T>() => undefined | (() => void);
|
||||
o5<number>()?.();
|
||||
|
||||
// GH#36031
|
||||
o2?.b()!.toString
|
||||
o2?.b()!.toString;
|
||||
o2?.b()!.toString!;
|
||||
+4
-2
@@ -26,5 +26,7 @@ declare const o6: <T>() => undefined | ({ x: number });
|
||||
o6<number>()?.["x"];
|
||||
|
||||
// GH#36031
|
||||
o2?.["b"]!.c
|
||||
o2?.["b"]!["c"]
|
||||
o2?.["b"]!.c;
|
||||
o2?.["b"]!["c"];
|
||||
o2?.["b"]!.c!;
|
||||
o2?.["b"]!["c"]!;
|
||||
+2
-1
@@ -23,4 +23,5 @@ o6<number>()?.x;
|
||||
o1?.b ? 1 : 0;
|
||||
|
||||
// GH#36031
|
||||
o2?.b!.c
|
||||
o2?.b!.c;
|
||||
o2?.b!.c!;
|
||||
Reference in New Issue
Block a user