Add check for delete expression must be optional (#37921)
* Add check for delete expression must be optional * Add more tests
This commit is contained in:
parent
052d3f9faf
commit
39beb1d011
|
@ -27583,12 +27583,23 @@ namespace ts {
|
||||||
}
|
}
|
||||||
const links = getNodeLinks(expr);
|
const links = getNodeLinks(expr);
|
||||||
const symbol = getExportSymbolOfValueSymbolIfExported(links.resolvedSymbol);
|
const symbol = getExportSymbolOfValueSymbolIfExported(links.resolvedSymbol);
|
||||||
if (symbol && isReadonlySymbol(symbol)) {
|
if (symbol) {
|
||||||
error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_read_only_property);
|
if (isReadonlySymbol(symbol)) {
|
||||||
|
error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_read_only_property);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkDeleteExpressionMustBeOptional(expr, getTypeOfSymbol(symbol));
|
||||||
}
|
}
|
||||||
return booleanType;
|
return booleanType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkDeleteExpressionMustBeOptional(expr: AccessExpression, type: Type) {
|
||||||
|
const AnyOrUnknownOrNeverFlags = TypeFlags.AnyOrUnknown | TypeFlags.Never;
|
||||||
|
if (strictNullChecks && !(type.flags & AnyOrUnknownOrNeverFlags) && !(getFalsyFlags(type) & TypeFlags.Undefined)) {
|
||||||
|
error(expr, Diagnostics.The_operand_of_a_delete_operator_must_be_optional);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function checkTypeOfExpression(node: TypeOfExpression): Type {
|
function checkTypeOfExpression(node: TypeOfExpression): Type {
|
||||||
checkExpression(node.expression);
|
checkExpression(node.expression);
|
||||||
return typeofType;
|
return typeofType;
|
||||||
|
|
|
@ -2963,6 +2963,10 @@
|
||||||
"category": "Error",
|
"category": "Error",
|
||||||
"code": 2789
|
"code": 2789
|
||||||
},
|
},
|
||||||
|
"The operand of a 'delete' operator must be optional.": {
|
||||||
|
"category": "Error",
|
||||||
|
"code": 2790
|
||||||
|
},
|
||||||
|
|
||||||
"Import declaration '{0}' is using private name '{1}'.": {
|
"Import declaration '{0}' is using private name '{1}'.": {
|
||||||
"category": "Error",
|
"category": "Error",
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
tests/cases/conformance/controlFlow/controlFlowDeleteOperator.ts(10,12): error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
tests/cases/conformance/controlFlow/controlFlowDeleteOperator.ts(14,12): error TS2703: The operand of a 'delete' operator must be a property reference.
|
tests/cases/conformance/controlFlow/controlFlowDeleteOperator.ts(14,12): error TS2703: The operand of a 'delete' operator must be a property reference.
|
||||||
|
|
||||||
|
|
||||||
==== tests/cases/conformance/controlFlow/controlFlowDeleteOperator.ts (1 errors) ====
|
==== tests/cases/conformance/controlFlow/controlFlowDeleteOperator.ts (2 errors) ====
|
||||||
function f() {
|
function f() {
|
||||||
let x: { a?: number | string, b: number | string } = { b: 1 };
|
let x: { a?: number | string, b: number | string } = { b: 1 };
|
||||||
x.a;
|
x.a;
|
||||||
|
@ -12,6 +13,8 @@ tests/cases/conformance/controlFlow/controlFlowDeleteOperator.ts(14,12): error T
|
||||||
x.b;
|
x.b;
|
||||||
delete x.a;
|
delete x.a;
|
||||||
delete x.b;
|
delete x.b;
|
||||||
|
~~~
|
||||||
|
!!! error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
x.a;
|
x.a;
|
||||||
x.b;
|
x.b;
|
||||||
x;
|
x;
|
||||||
|
|
66
tests/baselines/reference/deleteChain.errors.txt
Normal file
66
tests/baselines/reference/deleteChain.errors.txt
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(2,8): error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(3,9): error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(6,8): error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(7,9): error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(10,8): error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(11,9): error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(14,8): error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(15,8): error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(16,9): error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(19,8): error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(20,9): error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(23,8): error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(24,9): error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
|
||||||
|
|
||||||
|
==== tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts (13 errors) ====
|
||||||
|
declare const o1: undefined | { b: string };
|
||||||
|
delete o1?.b;
|
||||||
|
~~~~~
|
||||||
|
!!! error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
delete (o1?.b);
|
||||||
|
~~~~~
|
||||||
|
!!! error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
|
||||||
|
declare const o2: undefined | { b: { c: string } };
|
||||||
|
delete o2?.b.c;
|
||||||
|
~~~~~~~
|
||||||
|
!!! error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
delete (o2?.b.c);
|
||||||
|
~~~~~~~
|
||||||
|
!!! error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
|
||||||
|
declare const o3: { b: undefined | { c: string } };
|
||||||
|
delete o3.b?.c;
|
||||||
|
~~~~~~~
|
||||||
|
!!! error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
delete (o3.b?.c);
|
||||||
|
~~~~~~~
|
||||||
|
!!! error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
|
||||||
|
declare const o4: { b?: { c: { d?: { e: string } } } };
|
||||||
|
delete o4.b?.c.d?.e;
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
!!! error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
delete (o4.b?.c.d)?.e;
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
|
!!! error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
delete (o4.b?.c.d?.e);
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
!!! error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
|
||||||
|
declare const o5: { b?(): { c: { d?: { e: string } } } };
|
||||||
|
delete o5.b?.().c.d?.e;
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
!!! error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
delete (o5.b?.().c.d?.e);
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
!!! error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
|
||||||
|
declare const o6: { b?: { c: { d?: { e: string } } } };
|
||||||
|
delete o6.b?.['c'].d?.['e'];
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
!!! error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
delete (o6.b?.['c'].d?.['e']);
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
!!! error TS2790: The operand of a 'delete' operator must be optional.
|
|
@ -0,0 +1,46 @@
|
||||||
|
tests/cases/compiler/deleteExpressionMustBeOptional.ts(34,10): error TS2339: Property 'j' does not exist on type 'Foo'.
|
||||||
|
|
||||||
|
|
||||||
|
==== tests/cases/compiler/deleteExpressionMustBeOptional.ts (1 errors) ====
|
||||||
|
interface Foo {
|
||||||
|
a: number
|
||||||
|
b: number | undefined
|
||||||
|
c: number | null
|
||||||
|
d?: number
|
||||||
|
e: number | undefined | null
|
||||||
|
f?: number | undefined | null
|
||||||
|
g: unknown
|
||||||
|
h: any
|
||||||
|
i: never
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AA {
|
||||||
|
[s: string]: number
|
||||||
|
}
|
||||||
|
|
||||||
|
type BB = {
|
||||||
|
[P in keyof any]: number
|
||||||
|
}
|
||||||
|
|
||||||
|
declare const f: Foo
|
||||||
|
declare const a: AA
|
||||||
|
declare const b: BB
|
||||||
|
|
||||||
|
delete f.a
|
||||||
|
delete f.b
|
||||||
|
delete f.c
|
||||||
|
delete f.d
|
||||||
|
delete f.e
|
||||||
|
delete f.f
|
||||||
|
delete f.g
|
||||||
|
delete f.h
|
||||||
|
delete f.i
|
||||||
|
delete f.j
|
||||||
|
~
|
||||||
|
!!! error TS2339: Property 'j' does not exist on type 'Foo'.
|
||||||
|
|
||||||
|
delete a.a
|
||||||
|
delete a.b
|
||||||
|
|
||||||
|
delete b.a
|
||||||
|
delete b.b
|
|
@ -0,0 +1,57 @@
|
||||||
|
//// [deleteExpressionMustBeOptional.ts]
|
||||||
|
interface Foo {
|
||||||
|
a: number
|
||||||
|
b: number | undefined
|
||||||
|
c: number | null
|
||||||
|
d?: number
|
||||||
|
e: number | undefined | null
|
||||||
|
f?: number | undefined | null
|
||||||
|
g: unknown
|
||||||
|
h: any
|
||||||
|
i: never
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AA {
|
||||||
|
[s: string]: number
|
||||||
|
}
|
||||||
|
|
||||||
|
type BB = {
|
||||||
|
[P in keyof any]: number
|
||||||
|
}
|
||||||
|
|
||||||
|
declare const f: Foo
|
||||||
|
declare const a: AA
|
||||||
|
declare const b: BB
|
||||||
|
|
||||||
|
delete f.a
|
||||||
|
delete f.b
|
||||||
|
delete f.c
|
||||||
|
delete f.d
|
||||||
|
delete f.e
|
||||||
|
delete f.f
|
||||||
|
delete f.g
|
||||||
|
delete f.h
|
||||||
|
delete f.i
|
||||||
|
delete f.j
|
||||||
|
|
||||||
|
delete a.a
|
||||||
|
delete a.b
|
||||||
|
|
||||||
|
delete b.a
|
||||||
|
delete b.b
|
||||||
|
|
||||||
|
//// [deleteExpressionMustBeOptional.js]
|
||||||
|
delete f.a;
|
||||||
|
delete f.b;
|
||||||
|
delete f.c;
|
||||||
|
delete f.d;
|
||||||
|
delete f.e;
|
||||||
|
delete f.f;
|
||||||
|
delete f.g;
|
||||||
|
delete f.h;
|
||||||
|
delete f.i;
|
||||||
|
delete f.j;
|
||||||
|
delete a.a;
|
||||||
|
delete a.b;
|
||||||
|
delete b.a;
|
||||||
|
delete b.b;
|
|
@ -0,0 +1,118 @@
|
||||||
|
=== tests/cases/compiler/deleteExpressionMustBeOptional.ts ===
|
||||||
|
interface Foo {
|
||||||
|
>Foo : Symbol(Foo, Decl(deleteExpressionMustBeOptional.ts, 0, 0))
|
||||||
|
|
||||||
|
a: number
|
||||||
|
>a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15))
|
||||||
|
|
||||||
|
b: number | undefined
|
||||||
|
>b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13))
|
||||||
|
|
||||||
|
c: number | null
|
||||||
|
>c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25))
|
||||||
|
|
||||||
|
d?: number
|
||||||
|
>d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20))
|
||||||
|
|
||||||
|
e: number | undefined | null
|
||||||
|
>e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14))
|
||||||
|
|
||||||
|
f?: number | undefined | null
|
||||||
|
>f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32))
|
||||||
|
|
||||||
|
g: unknown
|
||||||
|
>g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33))
|
||||||
|
|
||||||
|
h: any
|
||||||
|
>h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14))
|
||||||
|
|
||||||
|
i: never
|
||||||
|
>i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10))
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AA {
|
||||||
|
>AA : Symbol(AA, Decl(deleteExpressionMustBeOptional.ts, 10, 1))
|
||||||
|
|
||||||
|
[s: string]: number
|
||||||
|
>s : Symbol(s, Decl(deleteExpressionMustBeOptional.ts, 13, 5))
|
||||||
|
}
|
||||||
|
|
||||||
|
type BB = {
|
||||||
|
>BB : Symbol(BB, Decl(deleteExpressionMustBeOptional.ts, 14, 1))
|
||||||
|
|
||||||
|
[P in keyof any]: number
|
||||||
|
>P : Symbol(P, Decl(deleteExpressionMustBeOptional.ts, 17, 5))
|
||||||
|
}
|
||||||
|
|
||||||
|
declare const f: Foo
|
||||||
|
>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13))
|
||||||
|
>Foo : Symbol(Foo, Decl(deleteExpressionMustBeOptional.ts, 0, 0))
|
||||||
|
|
||||||
|
declare const a: AA
|
||||||
|
>a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13))
|
||||||
|
>AA : Symbol(AA, Decl(deleteExpressionMustBeOptional.ts, 10, 1))
|
||||||
|
|
||||||
|
declare const b: BB
|
||||||
|
>b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13))
|
||||||
|
>BB : Symbol(BB, Decl(deleteExpressionMustBeOptional.ts, 14, 1))
|
||||||
|
|
||||||
|
delete f.a
|
||||||
|
>f.a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15))
|
||||||
|
>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13))
|
||||||
|
>a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15))
|
||||||
|
|
||||||
|
delete f.b
|
||||||
|
>f.b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13))
|
||||||
|
>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13))
|
||||||
|
>b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13))
|
||||||
|
|
||||||
|
delete f.c
|
||||||
|
>f.c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25))
|
||||||
|
>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13))
|
||||||
|
>c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25))
|
||||||
|
|
||||||
|
delete f.d
|
||||||
|
>f.d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20))
|
||||||
|
>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13))
|
||||||
|
>d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20))
|
||||||
|
|
||||||
|
delete f.e
|
||||||
|
>f.e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14))
|
||||||
|
>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13))
|
||||||
|
>e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14))
|
||||||
|
|
||||||
|
delete f.f
|
||||||
|
>f.f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32))
|
||||||
|
>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13))
|
||||||
|
>f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32))
|
||||||
|
|
||||||
|
delete f.g
|
||||||
|
>f.g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33))
|
||||||
|
>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13))
|
||||||
|
>g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33))
|
||||||
|
|
||||||
|
delete f.h
|
||||||
|
>f.h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14))
|
||||||
|
>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13))
|
||||||
|
>h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14))
|
||||||
|
|
||||||
|
delete f.i
|
||||||
|
>f.i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10))
|
||||||
|
>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13))
|
||||||
|
>i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10))
|
||||||
|
|
||||||
|
delete f.j
|
||||||
|
>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13))
|
||||||
|
|
||||||
|
delete a.a
|
||||||
|
>a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13))
|
||||||
|
|
||||||
|
delete a.b
|
||||||
|
>a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13))
|
||||||
|
|
||||||
|
delete b.a
|
||||||
|
>b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13))
|
||||||
|
|
||||||
|
delete b.b
|
||||||
|
>b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13))
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
=== tests/cases/compiler/deleteExpressionMustBeOptional.ts ===
|
||||||
|
interface Foo {
|
||||||
|
a: number
|
||||||
|
>a : number
|
||||||
|
|
||||||
|
b: number | undefined
|
||||||
|
>b : number
|
||||||
|
|
||||||
|
c: number | null
|
||||||
|
>c : number
|
||||||
|
>null : null
|
||||||
|
|
||||||
|
d?: number
|
||||||
|
>d : number
|
||||||
|
|
||||||
|
e: number | undefined | null
|
||||||
|
>e : number
|
||||||
|
>null : null
|
||||||
|
|
||||||
|
f?: number | undefined | null
|
||||||
|
>f : number
|
||||||
|
>null : null
|
||||||
|
|
||||||
|
g: unknown
|
||||||
|
>g : unknown
|
||||||
|
|
||||||
|
h: any
|
||||||
|
>h : any
|
||||||
|
|
||||||
|
i: never
|
||||||
|
>i : never
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AA {
|
||||||
|
[s: string]: number
|
||||||
|
>s : string
|
||||||
|
}
|
||||||
|
|
||||||
|
type BB = {
|
||||||
|
>BB : BB
|
||||||
|
|
||||||
|
[P in keyof any]: number
|
||||||
|
}
|
||||||
|
|
||||||
|
declare const f: Foo
|
||||||
|
>f : Foo
|
||||||
|
|
||||||
|
declare const a: AA
|
||||||
|
>a : AA
|
||||||
|
|
||||||
|
declare const b: BB
|
||||||
|
>b : BB
|
||||||
|
|
||||||
|
delete f.a
|
||||||
|
>delete f.a : boolean
|
||||||
|
>f.a : number
|
||||||
|
>f : Foo
|
||||||
|
>a : number
|
||||||
|
|
||||||
|
delete f.b
|
||||||
|
>delete f.b : boolean
|
||||||
|
>f.b : number
|
||||||
|
>f : Foo
|
||||||
|
>b : number
|
||||||
|
|
||||||
|
delete f.c
|
||||||
|
>delete f.c : boolean
|
||||||
|
>f.c : number
|
||||||
|
>f : Foo
|
||||||
|
>c : number
|
||||||
|
|
||||||
|
delete f.d
|
||||||
|
>delete f.d : boolean
|
||||||
|
>f.d : number
|
||||||
|
>f : Foo
|
||||||
|
>d : number
|
||||||
|
|
||||||
|
delete f.e
|
||||||
|
>delete f.e : boolean
|
||||||
|
>f.e : number
|
||||||
|
>f : Foo
|
||||||
|
>e : number
|
||||||
|
|
||||||
|
delete f.f
|
||||||
|
>delete f.f : boolean
|
||||||
|
>f.f : number
|
||||||
|
>f : Foo
|
||||||
|
>f : number
|
||||||
|
|
||||||
|
delete f.g
|
||||||
|
>delete f.g : boolean
|
||||||
|
>f.g : unknown
|
||||||
|
>f : Foo
|
||||||
|
>g : unknown
|
||||||
|
|
||||||
|
delete f.h
|
||||||
|
>delete f.h : boolean
|
||||||
|
>f.h : any
|
||||||
|
>f : Foo
|
||||||
|
>h : any
|
||||||
|
|
||||||
|
delete f.i
|
||||||
|
>delete f.i : boolean
|
||||||
|
>f.i : never
|
||||||
|
>f : Foo
|
||||||
|
>i : never
|
||||||
|
|
||||||
|
delete f.j
|
||||||
|
>delete f.j : boolean
|
||||||
|
>f.j : any
|
||||||
|
>f : Foo
|
||||||
|
>j : any
|
||||||
|
|
||||||
|
delete a.a
|
||||||
|
>delete a.a : boolean
|
||||||
|
>a.a : number
|
||||||
|
>a : AA
|
||||||
|
>a : number
|
||||||
|
|
||||||
|
delete a.b
|
||||||
|
>delete a.b : boolean
|
||||||
|
>a.b : number
|
||||||
|
>a : AA
|
||||||
|
>b : number
|
||||||
|
|
||||||
|
delete b.a
|
||||||
|
>delete b.a : boolean
|
||||||
|
>b.a : number
|
||||||
|
>b : BB
|
||||||
|
>a : number
|
||||||
|
|
||||||
|
delete b.b
|
||||||
|
>delete b.b : boolean
|
||||||
|
>b.b : number
|
||||||
|
>b : BB
|
||||||
|
>b : number
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
tests/cases/compiler/deleteExpressionMustBeOptional.ts(25,8): error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
tests/cases/compiler/deleteExpressionMustBeOptional.ts(27,8): error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
tests/cases/compiler/deleteExpressionMustBeOptional.ts(34,10): error TS2339: Property 'j' does not exist on type 'Foo'.
|
||||||
|
|
||||||
|
|
||||||
|
==== tests/cases/compiler/deleteExpressionMustBeOptional.ts (3 errors) ====
|
||||||
|
interface Foo {
|
||||||
|
a: number
|
||||||
|
b: number | undefined
|
||||||
|
c: number | null
|
||||||
|
d?: number
|
||||||
|
e: number | undefined | null
|
||||||
|
f?: number | undefined | null
|
||||||
|
g: unknown
|
||||||
|
h: any
|
||||||
|
i: never
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AA {
|
||||||
|
[s: string]: number
|
||||||
|
}
|
||||||
|
|
||||||
|
type BB = {
|
||||||
|
[P in keyof any]: number
|
||||||
|
}
|
||||||
|
|
||||||
|
declare const f: Foo
|
||||||
|
declare const a: AA
|
||||||
|
declare const b: BB
|
||||||
|
|
||||||
|
delete f.a
|
||||||
|
~~~
|
||||||
|
!!! error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
delete f.b
|
||||||
|
delete f.c
|
||||||
|
~~~
|
||||||
|
!!! error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
delete f.d
|
||||||
|
delete f.e
|
||||||
|
delete f.f
|
||||||
|
delete f.g
|
||||||
|
delete f.h
|
||||||
|
delete f.i
|
||||||
|
delete f.j
|
||||||
|
~
|
||||||
|
!!! error TS2339: Property 'j' does not exist on type 'Foo'.
|
||||||
|
|
||||||
|
delete a.a
|
||||||
|
delete a.b
|
||||||
|
|
||||||
|
delete b.a
|
||||||
|
delete b.b
|
|
@ -0,0 +1,58 @@
|
||||||
|
//// [deleteExpressionMustBeOptional.ts]
|
||||||
|
interface Foo {
|
||||||
|
a: number
|
||||||
|
b: number | undefined
|
||||||
|
c: number | null
|
||||||
|
d?: number
|
||||||
|
e: number | undefined | null
|
||||||
|
f?: number | undefined | null
|
||||||
|
g: unknown
|
||||||
|
h: any
|
||||||
|
i: never
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AA {
|
||||||
|
[s: string]: number
|
||||||
|
}
|
||||||
|
|
||||||
|
type BB = {
|
||||||
|
[P in keyof any]: number
|
||||||
|
}
|
||||||
|
|
||||||
|
declare const f: Foo
|
||||||
|
declare const a: AA
|
||||||
|
declare const b: BB
|
||||||
|
|
||||||
|
delete f.a
|
||||||
|
delete f.b
|
||||||
|
delete f.c
|
||||||
|
delete f.d
|
||||||
|
delete f.e
|
||||||
|
delete f.f
|
||||||
|
delete f.g
|
||||||
|
delete f.h
|
||||||
|
delete f.i
|
||||||
|
delete f.j
|
||||||
|
|
||||||
|
delete a.a
|
||||||
|
delete a.b
|
||||||
|
|
||||||
|
delete b.a
|
||||||
|
delete b.b
|
||||||
|
|
||||||
|
//// [deleteExpressionMustBeOptional.js]
|
||||||
|
"use strict";
|
||||||
|
delete f.a;
|
||||||
|
delete f.b;
|
||||||
|
delete f.c;
|
||||||
|
delete f.d;
|
||||||
|
delete f.e;
|
||||||
|
delete f.f;
|
||||||
|
delete f.g;
|
||||||
|
delete f.h;
|
||||||
|
delete f.i;
|
||||||
|
delete f.j;
|
||||||
|
delete a.a;
|
||||||
|
delete a.b;
|
||||||
|
delete b.a;
|
||||||
|
delete b.b;
|
|
@ -0,0 +1,118 @@
|
||||||
|
=== tests/cases/compiler/deleteExpressionMustBeOptional.ts ===
|
||||||
|
interface Foo {
|
||||||
|
>Foo : Symbol(Foo, Decl(deleteExpressionMustBeOptional.ts, 0, 0))
|
||||||
|
|
||||||
|
a: number
|
||||||
|
>a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15))
|
||||||
|
|
||||||
|
b: number | undefined
|
||||||
|
>b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13))
|
||||||
|
|
||||||
|
c: number | null
|
||||||
|
>c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25))
|
||||||
|
|
||||||
|
d?: number
|
||||||
|
>d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20))
|
||||||
|
|
||||||
|
e: number | undefined | null
|
||||||
|
>e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14))
|
||||||
|
|
||||||
|
f?: number | undefined | null
|
||||||
|
>f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32))
|
||||||
|
|
||||||
|
g: unknown
|
||||||
|
>g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33))
|
||||||
|
|
||||||
|
h: any
|
||||||
|
>h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14))
|
||||||
|
|
||||||
|
i: never
|
||||||
|
>i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10))
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AA {
|
||||||
|
>AA : Symbol(AA, Decl(deleteExpressionMustBeOptional.ts, 10, 1))
|
||||||
|
|
||||||
|
[s: string]: number
|
||||||
|
>s : Symbol(s, Decl(deleteExpressionMustBeOptional.ts, 13, 5))
|
||||||
|
}
|
||||||
|
|
||||||
|
type BB = {
|
||||||
|
>BB : Symbol(BB, Decl(deleteExpressionMustBeOptional.ts, 14, 1))
|
||||||
|
|
||||||
|
[P in keyof any]: number
|
||||||
|
>P : Symbol(P, Decl(deleteExpressionMustBeOptional.ts, 17, 5))
|
||||||
|
}
|
||||||
|
|
||||||
|
declare const f: Foo
|
||||||
|
>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13))
|
||||||
|
>Foo : Symbol(Foo, Decl(deleteExpressionMustBeOptional.ts, 0, 0))
|
||||||
|
|
||||||
|
declare const a: AA
|
||||||
|
>a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13))
|
||||||
|
>AA : Symbol(AA, Decl(deleteExpressionMustBeOptional.ts, 10, 1))
|
||||||
|
|
||||||
|
declare const b: BB
|
||||||
|
>b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13))
|
||||||
|
>BB : Symbol(BB, Decl(deleteExpressionMustBeOptional.ts, 14, 1))
|
||||||
|
|
||||||
|
delete f.a
|
||||||
|
>f.a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15))
|
||||||
|
>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13))
|
||||||
|
>a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15))
|
||||||
|
|
||||||
|
delete f.b
|
||||||
|
>f.b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13))
|
||||||
|
>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13))
|
||||||
|
>b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13))
|
||||||
|
|
||||||
|
delete f.c
|
||||||
|
>f.c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25))
|
||||||
|
>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13))
|
||||||
|
>c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25))
|
||||||
|
|
||||||
|
delete f.d
|
||||||
|
>f.d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20))
|
||||||
|
>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13))
|
||||||
|
>d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20))
|
||||||
|
|
||||||
|
delete f.e
|
||||||
|
>f.e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14))
|
||||||
|
>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13))
|
||||||
|
>e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14))
|
||||||
|
|
||||||
|
delete f.f
|
||||||
|
>f.f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32))
|
||||||
|
>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13))
|
||||||
|
>f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32))
|
||||||
|
|
||||||
|
delete f.g
|
||||||
|
>f.g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33))
|
||||||
|
>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13))
|
||||||
|
>g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33))
|
||||||
|
|
||||||
|
delete f.h
|
||||||
|
>f.h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14))
|
||||||
|
>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13))
|
||||||
|
>h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14))
|
||||||
|
|
||||||
|
delete f.i
|
||||||
|
>f.i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10))
|
||||||
|
>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13))
|
||||||
|
>i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10))
|
||||||
|
|
||||||
|
delete f.j
|
||||||
|
>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13))
|
||||||
|
|
||||||
|
delete a.a
|
||||||
|
>a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13))
|
||||||
|
|
||||||
|
delete a.b
|
||||||
|
>a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13))
|
||||||
|
|
||||||
|
delete b.a
|
||||||
|
>b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13))
|
||||||
|
|
||||||
|
delete b.b
|
||||||
|
>b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13))
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
=== tests/cases/compiler/deleteExpressionMustBeOptional.ts ===
|
||||||
|
interface Foo {
|
||||||
|
a: number
|
||||||
|
>a : number
|
||||||
|
|
||||||
|
b: number | undefined
|
||||||
|
>b : number | undefined
|
||||||
|
|
||||||
|
c: number | null
|
||||||
|
>c : number | null
|
||||||
|
>null : null
|
||||||
|
|
||||||
|
d?: number
|
||||||
|
>d : number | undefined
|
||||||
|
|
||||||
|
e: number | undefined | null
|
||||||
|
>e : number | null | undefined
|
||||||
|
>null : null
|
||||||
|
|
||||||
|
f?: number | undefined | null
|
||||||
|
>f : number | null | undefined
|
||||||
|
>null : null
|
||||||
|
|
||||||
|
g: unknown
|
||||||
|
>g : unknown
|
||||||
|
|
||||||
|
h: any
|
||||||
|
>h : any
|
||||||
|
|
||||||
|
i: never
|
||||||
|
>i : never
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AA {
|
||||||
|
[s: string]: number
|
||||||
|
>s : string
|
||||||
|
}
|
||||||
|
|
||||||
|
type BB = {
|
||||||
|
>BB : BB
|
||||||
|
|
||||||
|
[P in keyof any]: number
|
||||||
|
}
|
||||||
|
|
||||||
|
declare const f: Foo
|
||||||
|
>f : Foo
|
||||||
|
|
||||||
|
declare const a: AA
|
||||||
|
>a : AA
|
||||||
|
|
||||||
|
declare const b: BB
|
||||||
|
>b : BB
|
||||||
|
|
||||||
|
delete f.a
|
||||||
|
>delete f.a : boolean
|
||||||
|
>f.a : number
|
||||||
|
>f : Foo
|
||||||
|
>a : number
|
||||||
|
|
||||||
|
delete f.b
|
||||||
|
>delete f.b : boolean
|
||||||
|
>f.b : number | undefined
|
||||||
|
>f : Foo
|
||||||
|
>b : number | undefined
|
||||||
|
|
||||||
|
delete f.c
|
||||||
|
>delete f.c : boolean
|
||||||
|
>f.c : number | null
|
||||||
|
>f : Foo
|
||||||
|
>c : number | null
|
||||||
|
|
||||||
|
delete f.d
|
||||||
|
>delete f.d : boolean
|
||||||
|
>f.d : number | undefined
|
||||||
|
>f : Foo
|
||||||
|
>d : number | undefined
|
||||||
|
|
||||||
|
delete f.e
|
||||||
|
>delete f.e : boolean
|
||||||
|
>f.e : number | null | undefined
|
||||||
|
>f : Foo
|
||||||
|
>e : number | null | undefined
|
||||||
|
|
||||||
|
delete f.f
|
||||||
|
>delete f.f : boolean
|
||||||
|
>f.f : number | null | undefined
|
||||||
|
>f : Foo
|
||||||
|
>f : number | null | undefined
|
||||||
|
|
||||||
|
delete f.g
|
||||||
|
>delete f.g : boolean
|
||||||
|
>f.g : unknown
|
||||||
|
>f : Foo
|
||||||
|
>g : unknown
|
||||||
|
|
||||||
|
delete f.h
|
||||||
|
>delete f.h : boolean
|
||||||
|
>f.h : any
|
||||||
|
>f : Foo
|
||||||
|
>h : any
|
||||||
|
|
||||||
|
delete f.i
|
||||||
|
>delete f.i : boolean
|
||||||
|
>f.i : never
|
||||||
|
>f : Foo
|
||||||
|
>i : never
|
||||||
|
|
||||||
|
delete f.j
|
||||||
|
>delete f.j : boolean
|
||||||
|
>f.j : any
|
||||||
|
>f : Foo
|
||||||
|
>j : any
|
||||||
|
|
||||||
|
delete a.a
|
||||||
|
>delete a.a : boolean
|
||||||
|
>a.a : number
|
||||||
|
>a : AA
|
||||||
|
>a : number
|
||||||
|
|
||||||
|
delete a.b
|
||||||
|
>delete a.b : boolean
|
||||||
|
>a.b : number
|
||||||
|
>a : AA
|
||||||
|
>b : number
|
||||||
|
|
||||||
|
delete b.a
|
||||||
|
>delete b.a : boolean
|
||||||
|
>b.a : number
|
||||||
|
>b : BB
|
||||||
|
>a : number
|
||||||
|
|
||||||
|
delete b.b
|
||||||
|
>delete b.b : boolean
|
||||||
|
>b.b : number
|
||||||
|
>b : BB
|
||||||
|
>b : number
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
|
tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts(4,16): error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts(4,16): error TS18011: The operand of a 'delete' operator cannot be a private identifier.
|
tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts(4,16): error TS18011: The operand of a 'delete' operator cannot be a private identifier.
|
||||||
|
|
||||||
|
|
||||||
==== tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts (1 errors) ====
|
==== tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts (2 errors) ====
|
||||||
class A {
|
class A {
|
||||||
#v = 1;
|
#v = 1;
|
||||||
constructor() {
|
constructor() {
|
||||||
delete this.#v; // Error: The operand of a delete operator cannot be a private name.
|
delete this.#v; // Error: The operand of a delete operator cannot be a private name.
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
|
!!! error TS2790: The operand of a 'delete' operator must be optional.
|
||||||
|
~~~~~~~
|
||||||
!!! error TS18011: The operand of a 'delete' operator cannot be a private identifier.
|
!!! error TS18011: The operand of a 'delete' operator cannot be a private identifier.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
42
tests/cases/compiler/deleteExpressionMustBeOptional.ts
Normal file
42
tests/cases/compiler/deleteExpressionMustBeOptional.ts
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
// @strict: true, false
|
||||||
|
|
||||||
|
interface Foo {
|
||||||
|
a: number
|
||||||
|
b: number | undefined
|
||||||
|
c: number | null
|
||||||
|
d?: number
|
||||||
|
e: number | undefined | null
|
||||||
|
f?: number | undefined | null
|
||||||
|
g: unknown
|
||||||
|
h: any
|
||||||
|
i: never
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AA {
|
||||||
|
[s: string]: number
|
||||||
|
}
|
||||||
|
|
||||||
|
type BB = {
|
||||||
|
[P in keyof any]: number
|
||||||
|
}
|
||||||
|
|
||||||
|
declare const f: Foo
|
||||||
|
declare const a: AA
|
||||||
|
declare const b: BB
|
||||||
|
|
||||||
|
delete f.a
|
||||||
|
delete f.b
|
||||||
|
delete f.c
|
||||||
|
delete f.d
|
||||||
|
delete f.e
|
||||||
|
delete f.f
|
||||||
|
delete f.g
|
||||||
|
delete f.h
|
||||||
|
delete f.i
|
||||||
|
delete f.j
|
||||||
|
|
||||||
|
delete a.a
|
||||||
|
delete a.b
|
||||||
|
|
||||||
|
delete b.a
|
||||||
|
delete b.b
|
Loading…
Reference in a new issue