diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index ab3ecdc9228..2300feeb0e2 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -24,7 +24,7 @@ namespace ts { case SyntaxKind.ElementAccessExpression: case SyntaxKind.CallExpression: if (node.flags & NodeFlags.OptionalChain) { - const updated = visitOptionalExpression(node as OptionalChain, /*captureThisArg*/ false); + const updated = visitOptionalExpression(node as OptionalChain, /*captureThisArg*/ false, /*isDelete*/ false); Debug.assertNotNode(updated, isSyntheticReference); return updated; } @@ -34,6 +34,8 @@ namespace ts { return transformNullishCoalescingExpression(node); } return visitEachChild(node, visitor, context); + case SyntaxKind.DeleteExpression: + return visitDeleteExpression(node as DeleteExpression); default: return visitEachChild(node, visitor, context); } @@ -48,8 +50,8 @@ namespace ts { return { expression: chain.expression, chain: links }; } - function visitNonOptionalParenthesizedExpression(node: ParenthesizedExpression, captureThisArg: boolean): Expression { - const expression = visitNonOptionalExpression(node.expression, captureThisArg); + function visitNonOptionalParenthesizedExpression(node: ParenthesizedExpression, captureThisArg: boolean, isDelete: boolean): Expression { + const expression = visitNonOptionalExpression(node.expression, captureThisArg, isDelete); if (isSyntheticReference(expression)) { // `(a.b)` -> { expression `((_a = a).b)`, thisArg: `_a` } // `(a[b])` -> { expression `((_a = a)[b])`, thisArg: `_a` } @@ -58,10 +60,10 @@ namespace ts { return updateParen(node, expression); } - function visitNonOptionalPropertyOrElementAccessExpression(node: AccessExpression, captureThisArg: boolean): Expression { + function visitNonOptionalPropertyOrElementAccessExpression(node: AccessExpression, captureThisArg: boolean, isDelete: boolean): Expression { if (isOptionalChain(node)) { // If `node` is an optional chain, then it is the outermost chain of an optional expression. - return visitOptionalExpression(node, captureThisArg); + return visitOptionalExpression(node, captureThisArg, isDelete); } let expression: Expression = visitNode(node.expression, visitor, isExpression); @@ -87,24 +89,24 @@ namespace ts { function visitNonOptionalCallExpression(node: CallExpression, captureThisArg: boolean): Expression { if (isOptionalChain(node)) { // If `node` is an optional chain, then it is the outermost chain of an optional expression. - return visitOptionalExpression(node, captureThisArg); + return visitOptionalExpression(node, captureThisArg, /*isDelete*/ false); } return visitEachChild(node, visitor, context); } - function visitNonOptionalExpression(node: Expression, captureThisArg: boolean): Expression { + function visitNonOptionalExpression(node: Expression, captureThisArg: boolean, isDelete: boolean): Expression { switch (node.kind) { - case SyntaxKind.ParenthesizedExpression: return visitNonOptionalParenthesizedExpression(node as ParenthesizedExpression, captureThisArg); + case SyntaxKind.ParenthesizedExpression: return visitNonOptionalParenthesizedExpression(node as ParenthesizedExpression, captureThisArg, isDelete); case SyntaxKind.PropertyAccessExpression: - case SyntaxKind.ElementAccessExpression: return visitNonOptionalPropertyOrElementAccessExpression(node as AccessExpression, captureThisArg); + case SyntaxKind.ElementAccessExpression: return visitNonOptionalPropertyOrElementAccessExpression(node as AccessExpression, captureThisArg, isDelete); case SyntaxKind.CallExpression: return visitNonOptionalCallExpression(node as CallExpression, captureThisArg); default: return visitNode(node, visitor, isExpression); } } - function visitOptionalExpression(node: OptionalChain, captureThisArg: boolean): Expression { + function visitOptionalExpression(node: OptionalChain, captureThisArg: boolean, isDelete: boolean): Expression { const { expression, chain } = flattenChain(node); - const left = visitNonOptionalExpression(expression, isCallChain(chain[0])); + const left = visitNonOptionalExpression(expression, isCallChain(chain[0]), /*isDelete*/ false); const leftThisArg = isSyntheticReference(left) ? left.thisArg : undefined; let leftExpression = isSyntheticReference(left) ? left.expression : left; let capturedLeft: Expression = leftExpression; @@ -152,11 +154,9 @@ namespace ts { setOriginalNode(rightExpression, segment); } - const target = createConditional( - createNotNullCondition(leftExpression, capturedLeft, /*invert*/ true), - createVoidZero(), - rightExpression, - ); + const target = isDelete + ? createConditional(createNotNullCondition(leftExpression, capturedLeft, /*invert*/ true), createTrue(), createDelete(rightExpression)) + : createConditional(createNotNullCondition(leftExpression, capturedLeft, /*invert*/ true), createVoidZero(), rightExpression); return thisArg ? createSyntheticReferenceExpression(target, thisArg) : target; } @@ -197,5 +197,11 @@ namespace ts { expression.kind !== SyntaxKind.ThisKeyword && expression.kind !== SyntaxKind.SuperKeyword; } + + function visitDeleteExpression(node: DeleteExpression) { + return isOptionalChain(skipParentheses(node.expression)) + ? setOriginalNode(visitNonOptionalExpression(node.expression, /*captureThisArg*/ false, /*isDelete*/ true), node) + : updateDelete(node, visitNode(node.expression, visitor, isExpression)); + } } } diff --git a/tests/baselines/reference/deleteChain.js b/tests/baselines/reference/deleteChain.js new file mode 100644 index 00000000000..1cf168d2724 --- /dev/null +++ b/tests/baselines/reference/deleteChain.js @@ -0,0 +1,42 @@ +//// [deleteChain.ts] +declare const o1: undefined | { b: string }; +delete o1?.b; +delete (o1?.b); + +declare const o2: undefined | { b: { c: string } }; +delete o2?.b.c; +delete (o2?.b.c); + +declare const o3: { b: undefined | { c: string } }; +delete o3.b?.c; +delete (o3.b?.c); + +declare const o4: { b?: { c: { d?: { e: string } } } }; +delete o4.b?.c.d?.e; +delete (o4.b?.c.d)?.e; +delete (o4.b?.c.d?.e); + +declare const o5: { b?(): { c: { d?: { e: string } } } }; +delete o5.b?.().c.d?.e; +delete (o5.b?.().c.d?.e); + +declare const o6: { b?: { c: { d?: { e: string } } } }; +delete o6.b?.['c'].d?.['e']; +delete (o6.b?.['c'].d?.['e']); + +//// [deleteChain.js] +"use strict"; +var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r; +o1 === null || o1 === void 0 ? true : delete o1.b; +(o1 === null || o1 === void 0 ? true : delete o1.b); +o2 === null || o2 === void 0 ? true : delete o2.b.c; +(o2 === null || o2 === void 0 ? true : delete o2.b.c); +(_a = o3.b) === null || _a === void 0 ? true : delete _a.c; +((_b = o3.b) === null || _b === void 0 ? true : delete _b.c); +(_d = (_c = o4.b) === null || _c === void 0 ? void 0 : _c.c.d) === null || _d === void 0 ? true : delete _d.e; +(_f = ((_e = o4.b) === null || _e === void 0 ? void 0 : _e.c.d)) === null || _f === void 0 ? true : delete _f.e; +((_h = (_g = o4.b) === null || _g === void 0 ? void 0 : _g.c.d) === null || _h === void 0 ? true : delete _h.e); +(_k = (_j = o5.b) === null || _j === void 0 ? void 0 : _j.call(o5).c.d) === null || _k === void 0 ? true : delete _k.e; +((_m = (_l = o5.b) === null || _l === void 0 ? void 0 : _l.call(o5).c.d) === null || _m === void 0 ? true : delete _m.e); +(_p = (_o = o6.b) === null || _o === void 0 ? void 0 : _o['c'].d) === null || _p === void 0 ? true : delete _p['e']; +((_r = (_q = o6.b) === null || _q === void 0 ? void 0 : _q['c'].d) === null || _r === void 0 ? true : delete _r['e']); diff --git a/tests/baselines/reference/deleteChain.symbols b/tests/baselines/reference/deleteChain.symbols new file mode 100644 index 00000000000..7efc0abae47 --- /dev/null +++ b/tests/baselines/reference/deleteChain.symbols @@ -0,0 +1,143 @@ +=== tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts === +declare const o1: undefined | { b: string }; +>o1 : Symbol(o1, Decl(deleteChain.ts, 0, 13)) +>b : Symbol(b, Decl(deleteChain.ts, 0, 31)) + +delete o1?.b; +>o1?.b : Symbol(b, Decl(deleteChain.ts, 0, 31)) +>o1 : Symbol(o1, Decl(deleteChain.ts, 0, 13)) +>b : Symbol(b, Decl(deleteChain.ts, 0, 31)) + +delete (o1?.b); +>o1?.b : Symbol(b, Decl(deleteChain.ts, 0, 31)) +>o1 : Symbol(o1, Decl(deleteChain.ts, 0, 13)) +>b : Symbol(b, Decl(deleteChain.ts, 0, 31)) + +declare const o2: undefined | { b: { c: string } }; +>o2 : Symbol(o2, Decl(deleteChain.ts, 4, 13)) +>b : Symbol(b, Decl(deleteChain.ts, 4, 31)) +>c : Symbol(c, Decl(deleteChain.ts, 4, 36)) + +delete o2?.b.c; +>o2?.b.c : Symbol(c, Decl(deleteChain.ts, 4, 36)) +>o2?.b : Symbol(b, Decl(deleteChain.ts, 4, 31)) +>o2 : Symbol(o2, Decl(deleteChain.ts, 4, 13)) +>b : Symbol(b, Decl(deleteChain.ts, 4, 31)) +>c : Symbol(c, Decl(deleteChain.ts, 4, 36)) + +delete (o2?.b.c); +>o2?.b.c : Symbol(c, Decl(deleteChain.ts, 4, 36)) +>o2?.b : Symbol(b, Decl(deleteChain.ts, 4, 31)) +>o2 : Symbol(o2, Decl(deleteChain.ts, 4, 13)) +>b : Symbol(b, Decl(deleteChain.ts, 4, 31)) +>c : Symbol(c, Decl(deleteChain.ts, 4, 36)) + +declare const o3: { b: undefined | { c: string } }; +>o3 : Symbol(o3, Decl(deleteChain.ts, 8, 13)) +>b : Symbol(b, Decl(deleteChain.ts, 8, 19)) +>c : Symbol(c, Decl(deleteChain.ts, 8, 36)) + +delete o3.b?.c; +>o3.b?.c : Symbol(c, Decl(deleteChain.ts, 8, 36)) +>o3.b : Symbol(b, Decl(deleteChain.ts, 8, 19)) +>o3 : Symbol(o3, Decl(deleteChain.ts, 8, 13)) +>b : Symbol(b, Decl(deleteChain.ts, 8, 19)) +>c : Symbol(c, Decl(deleteChain.ts, 8, 36)) + +delete (o3.b?.c); +>o3.b?.c : Symbol(c, Decl(deleteChain.ts, 8, 36)) +>o3.b : Symbol(b, Decl(deleteChain.ts, 8, 19)) +>o3 : Symbol(o3, Decl(deleteChain.ts, 8, 13)) +>b : Symbol(b, Decl(deleteChain.ts, 8, 19)) +>c : Symbol(c, Decl(deleteChain.ts, 8, 36)) + +declare const o4: { b?: { c: { d?: { e: string } } } }; +>o4 : Symbol(o4, Decl(deleteChain.ts, 12, 13)) +>b : Symbol(b, Decl(deleteChain.ts, 12, 19)) +>c : Symbol(c, Decl(deleteChain.ts, 12, 25)) +>d : Symbol(d, Decl(deleteChain.ts, 12, 30)) +>e : Symbol(e, Decl(deleteChain.ts, 12, 36)) + +delete o4.b?.c.d?.e; +>o4.b?.c.d?.e : Symbol(e, Decl(deleteChain.ts, 12, 36)) +>o4.b?.c.d : Symbol(d, Decl(deleteChain.ts, 12, 30)) +>o4.b?.c : Symbol(c, Decl(deleteChain.ts, 12, 25)) +>o4.b : Symbol(b, Decl(deleteChain.ts, 12, 19)) +>o4 : Symbol(o4, Decl(deleteChain.ts, 12, 13)) +>b : Symbol(b, Decl(deleteChain.ts, 12, 19)) +>c : Symbol(c, Decl(deleteChain.ts, 12, 25)) +>d : Symbol(d, Decl(deleteChain.ts, 12, 30)) +>e : Symbol(e, Decl(deleteChain.ts, 12, 36)) + +delete (o4.b?.c.d)?.e; +>(o4.b?.c.d)?.e : Symbol(e, Decl(deleteChain.ts, 12, 36)) +>o4.b?.c.d : Symbol(d, Decl(deleteChain.ts, 12, 30)) +>o4.b?.c : Symbol(c, Decl(deleteChain.ts, 12, 25)) +>o4.b : Symbol(b, Decl(deleteChain.ts, 12, 19)) +>o4 : Symbol(o4, Decl(deleteChain.ts, 12, 13)) +>b : Symbol(b, Decl(deleteChain.ts, 12, 19)) +>c : Symbol(c, Decl(deleteChain.ts, 12, 25)) +>d : Symbol(d, Decl(deleteChain.ts, 12, 30)) +>e : Symbol(e, Decl(deleteChain.ts, 12, 36)) + +delete (o4.b?.c.d?.e); +>o4.b?.c.d?.e : Symbol(e, Decl(deleteChain.ts, 12, 36)) +>o4.b?.c.d : Symbol(d, Decl(deleteChain.ts, 12, 30)) +>o4.b?.c : Symbol(c, Decl(deleteChain.ts, 12, 25)) +>o4.b : Symbol(b, Decl(deleteChain.ts, 12, 19)) +>o4 : Symbol(o4, Decl(deleteChain.ts, 12, 13)) +>b : Symbol(b, Decl(deleteChain.ts, 12, 19)) +>c : Symbol(c, Decl(deleteChain.ts, 12, 25)) +>d : Symbol(d, Decl(deleteChain.ts, 12, 30)) +>e : Symbol(e, Decl(deleteChain.ts, 12, 36)) + +declare const o5: { b?(): { c: { d?: { e: string } } } }; +>o5 : Symbol(o5, Decl(deleteChain.ts, 17, 13)) +>b : Symbol(b, Decl(deleteChain.ts, 17, 19)) +>c : Symbol(c, Decl(deleteChain.ts, 17, 27)) +>d : Symbol(d, Decl(deleteChain.ts, 17, 32)) +>e : Symbol(e, Decl(deleteChain.ts, 17, 38)) + +delete o5.b?.().c.d?.e; +>o5.b?.().c.d?.e : Symbol(e, Decl(deleteChain.ts, 17, 38)) +>o5.b?.().c.d : Symbol(d, Decl(deleteChain.ts, 17, 32)) +>o5.b?.().c : Symbol(c, Decl(deleteChain.ts, 17, 27)) +>o5.b : Symbol(b, Decl(deleteChain.ts, 17, 19)) +>o5 : Symbol(o5, Decl(deleteChain.ts, 17, 13)) +>b : Symbol(b, Decl(deleteChain.ts, 17, 19)) +>c : Symbol(c, Decl(deleteChain.ts, 17, 27)) +>d : Symbol(d, Decl(deleteChain.ts, 17, 32)) +>e : Symbol(e, Decl(deleteChain.ts, 17, 38)) + +delete (o5.b?.().c.d?.e); +>o5.b?.().c.d?.e : Symbol(e, Decl(deleteChain.ts, 17, 38)) +>o5.b?.().c.d : Symbol(d, Decl(deleteChain.ts, 17, 32)) +>o5.b?.().c : Symbol(c, Decl(deleteChain.ts, 17, 27)) +>o5.b : Symbol(b, Decl(deleteChain.ts, 17, 19)) +>o5 : Symbol(o5, Decl(deleteChain.ts, 17, 13)) +>b : Symbol(b, Decl(deleteChain.ts, 17, 19)) +>c : Symbol(c, Decl(deleteChain.ts, 17, 27)) +>d : Symbol(d, Decl(deleteChain.ts, 17, 32)) +>e : Symbol(e, Decl(deleteChain.ts, 17, 38)) + +declare const o6: { b?: { c: { d?: { e: string } } } }; +>o6 : Symbol(o6, Decl(deleteChain.ts, 21, 13)) +>b : Symbol(b, Decl(deleteChain.ts, 21, 19)) +>c : Symbol(c, Decl(deleteChain.ts, 21, 25)) +>d : Symbol(d, Decl(deleteChain.ts, 21, 30)) +>e : Symbol(e, Decl(deleteChain.ts, 21, 36)) + +delete o6.b?.['c'].d?.['e']; +>o6.b?.['c'].d : Symbol(d, Decl(deleteChain.ts, 21, 30)) +>o6.b : Symbol(b, Decl(deleteChain.ts, 21, 19)) +>o6 : Symbol(o6, Decl(deleteChain.ts, 21, 13)) +>b : Symbol(b, Decl(deleteChain.ts, 21, 19)) +>d : Symbol(d, Decl(deleteChain.ts, 21, 30)) + +delete (o6.b?.['c'].d?.['e']); +>o6.b?.['c'].d : Symbol(d, Decl(deleteChain.ts, 21, 30)) +>o6.b : Symbol(b, Decl(deleteChain.ts, 21, 19)) +>o6 : Symbol(o6, Decl(deleteChain.ts, 21, 13)) +>b : Symbol(b, Decl(deleteChain.ts, 21, 19)) +>d : Symbol(d, Decl(deleteChain.ts, 21, 30)) + diff --git a/tests/baselines/reference/deleteChain.types b/tests/baselines/reference/deleteChain.types new file mode 100644 index 00000000000..ab7fd8e65b1 --- /dev/null +++ b/tests/baselines/reference/deleteChain.types @@ -0,0 +1,173 @@ +=== tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts === +declare const o1: undefined | { b: string }; +>o1 : { b: string; } | undefined +>b : string + +delete o1?.b; +>delete o1?.b : boolean +>o1?.b : string | undefined +>o1 : { b: string; } | undefined +>b : string | undefined + +delete (o1?.b); +>delete (o1?.b) : boolean +>(o1?.b) : string | undefined +>o1?.b : string | undefined +>o1 : { b: string; } | undefined +>b : string | undefined + +declare const o2: undefined | { b: { c: string } }; +>o2 : { b: { c: string; }; } | undefined +>b : { c: string; } +>c : string + +delete o2?.b.c; +>delete o2?.b.c : boolean +>o2?.b.c : string | undefined +>o2?.b : { c: string; } | undefined +>o2 : { b: { c: string; }; } | undefined +>b : { c: string; } | undefined +>c : string | undefined + +delete (o2?.b.c); +>delete (o2?.b.c) : boolean +>(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 + +declare const o3: { b: undefined | { c: string } }; +>o3 : { b: { c: string; } | undefined; } +>b : { c: string; } | undefined +>c : string + +delete o3.b?.c; +>delete o3.b?.c : boolean +>o3.b?.c : string | undefined +>o3.b : { c: string; } | undefined +>o3 : { b: { c: string; } | undefined; } +>b : { c: string; } | undefined +>c : string | undefined + +delete (o3.b?.c); +>delete (o3.b?.c) : boolean +>(o3.b?.c) : string | undefined +>o3.b?.c : string | undefined +>o3.b : { c: string; } | undefined +>o3 : { b: { c: string; } | undefined; } +>b : { c: string; } | undefined +>c : string | undefined + +declare const o4: { b?: { c: { d?: { e: string } } } }; +>o4 : { b?: { c: { d?: { e: string; } | undefined; }; } | undefined; } +>b : { c: { d?: { e: string; } | undefined; }; } | undefined +>c : { d?: { e: string; } | undefined; } +>d : { e: string; } | undefined +>e : string + +delete o4.b?.c.d?.e; +>delete o4.b?.c.d?.e : boolean +>o4.b?.c.d?.e : string | undefined +>o4.b?.c.d : { e: string; } | undefined +>o4.b?.c : { d?: { e: string; } | undefined; } | undefined +>o4.b : { c: { d?: { e: string; } | undefined; }; } | undefined +>o4 : { b?: { c: { d?: { e: string; } | undefined; }; } | undefined; } +>b : { c: { d?: { e: string; } | undefined; }; } | undefined +>c : { d?: { e: string; } | undefined; } | undefined +>d : { e: string; } | undefined +>e : string | undefined + +delete (o4.b?.c.d)?.e; +>delete (o4.b?.c.d)?.e : boolean +>(o4.b?.c.d)?.e : string | undefined +>(o4.b?.c.d) : { e: string; } | undefined +>o4.b?.c.d : { e: string; } | undefined +>o4.b?.c : { d?: { e: string; } | undefined; } | undefined +>o4.b : { c: { d?: { e: string; } | undefined; }; } | undefined +>o4 : { b?: { c: { d?: { e: string; } | undefined; }; } | undefined; } +>b : { c: { d?: { e: string; } | undefined; }; } | undefined +>c : { d?: { e: string; } | undefined; } | undefined +>d : { e: string; } | undefined +>e : string | undefined + +delete (o4.b?.c.d?.e); +>delete (o4.b?.c.d?.e) : boolean +>(o4.b?.c.d?.e) : string | undefined +>o4.b?.c.d?.e : string | undefined +>o4.b?.c.d : { e: string; } | undefined +>o4.b?.c : { d?: { e: string; } | undefined; } | undefined +>o4.b : { c: { d?: { e: string; } | undefined; }; } | undefined +>o4 : { b?: { c: { d?: { e: string; } | undefined; }; } | undefined; } +>b : { c: { d?: { e: string; } | undefined; }; } | undefined +>c : { d?: { e: string; } | undefined; } | undefined +>d : { e: string; } | undefined +>e : string | undefined + +declare const o5: { b?(): { c: { d?: { e: string } } } }; +>o5 : { b?(): { c: { d?: { e: string; } | undefined; }; }; } +>b : (() => { c: { d?: { e: string; } | undefined; }; }) | undefined +>c : { d?: { e: string; } | undefined; } +>d : { e: string; } | undefined +>e : string + +delete o5.b?.().c.d?.e; +>delete o5.b?.().c.d?.e : boolean +>o5.b?.().c.d?.e : string | undefined +>o5.b?.().c.d : { e: string; } | undefined +>o5.b?.().c : { d?: { e: string; } | undefined; } | undefined +>o5.b?.() : { c: { d?: { e: string; } | undefined; }; } | undefined +>o5.b : (() => { c: { d?: { e: string; } | undefined; }; }) | undefined +>o5 : { b?(): { c: { d?: { e: string; } | undefined; }; }; } +>b : (() => { c: { d?: { e: string; } | undefined; }; }) | undefined +>c : { d?: { e: string; } | undefined; } | undefined +>d : { e: string; } | undefined +>e : string | undefined + +delete (o5.b?.().c.d?.e); +>delete (o5.b?.().c.d?.e) : boolean +>(o5.b?.().c.d?.e) : string | undefined +>o5.b?.().c.d?.e : string | undefined +>o5.b?.().c.d : { e: string; } | undefined +>o5.b?.().c : { d?: { e: string; } | undefined; } | undefined +>o5.b?.() : { c: { d?: { e: string; } | undefined; }; } | undefined +>o5.b : (() => { c: { d?: { e: string; } | undefined; }; }) | undefined +>o5 : { b?(): { c: { d?: { e: string; } | undefined; }; }; } +>b : (() => { c: { d?: { e: string; } | undefined; }; }) | undefined +>c : { d?: { e: string; } | undefined; } | undefined +>d : { e: string; } | undefined +>e : string | undefined + +declare const o6: { b?: { c: { d?: { e: string } } } }; +>o6 : { b?: { c: { d?: { e: string; } | undefined; }; } | undefined; } +>b : { c: { d?: { e: string; } | undefined; }; } | undefined +>c : { d?: { e: string; } | undefined; } +>d : { e: string; } | undefined +>e : string + +delete o6.b?.['c'].d?.['e']; +>delete o6.b?.['c'].d?.['e'] : boolean +>o6.b?.['c'].d?.['e'] : string | undefined +>o6.b?.['c'].d : { e: string; } | undefined +>o6.b?.['c'] : { d?: { e: string; } | undefined; } | undefined +>o6.b : { c: { d?: { e: string; } | undefined; }; } | undefined +>o6 : { b?: { c: { d?: { e: string; } | undefined; }; } | undefined; } +>b : { c: { d?: { e: string; } | undefined; }; } | undefined +>'c' : "c" +>d : { e: string; } | undefined +>'e' : "e" + +delete (o6.b?.['c'].d?.['e']); +>delete (o6.b?.['c'].d?.['e']) : boolean +>(o6.b?.['c'].d?.['e']) : string | undefined +>o6.b?.['c'].d?.['e'] : string | undefined +>o6.b?.['c'].d : { e: string; } | undefined +>o6.b?.['c'] : { d?: { e: string; } | undefined; } | undefined +>o6.b : { c: { d?: { e: string; } | undefined; }; } | undefined +>o6 : { b?: { c: { d?: { e: string; } | undefined; }; } | undefined; } +>b : { c: { d?: { e: string; } | undefined; }; } | undefined +>'c' : "c" +>d : { e: string; } | undefined +>'e' : "e" + diff --git a/tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts b/tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts new file mode 100644 index 00000000000..878689704b7 --- /dev/null +++ b/tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts @@ -0,0 +1,26 @@ +// @strict: true + +declare const o1: undefined | { b: string }; +delete o1?.b; +delete (o1?.b); + +declare const o2: undefined | { b: { c: string } }; +delete o2?.b.c; +delete (o2?.b.c); + +declare const o3: { b: undefined | { c: string } }; +delete o3.b?.c; +delete (o3.b?.c); + +declare const o4: { b?: { c: { d?: { e: string } } } }; +delete o4.b?.c.d?.e; +delete (o4.b?.c.d)?.e; +delete (o4.b?.c.d?.e); + +declare const o5: { b?(): { c: { d?: { e: string } } } }; +delete o5.b?.().c.d?.e; +delete (o5.b?.().c.d?.e); + +declare const o6: { b?: { c: { d?: { e: string } } } }; +delete o6.b?.['c'].d?.['e']; +delete (o6.b?.['c'].d?.['e']); \ No newline at end of file