mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-15 03:23:08 -06:00
fix(41420): forbid optional chain in extends/implements (#41481)
This commit is contained in:
parent
6fac3ddfd4
commit
b405fdd2ab
@ -35660,7 +35660,7 @@ namespace ts {
|
||||
const implementedTypeNodes = getEffectiveImplementsTypeNodes(node);
|
||||
if (implementedTypeNodes) {
|
||||
for (const typeRefNode of implementedTypeNodes) {
|
||||
if (!isEntityNameExpression(typeRefNode.expression)) {
|
||||
if (!isEntityNameExpression(typeRefNode.expression) || isOptionalChain(typeRefNode.expression)) {
|
||||
error(typeRefNode.expression, Diagnostics.A_class_can_only_implement_an_identifier_Slashqualified_name_with_optional_type_arguments);
|
||||
}
|
||||
checkTypeReferenceNode(typeRefNode);
|
||||
@ -36009,7 +36009,7 @@ namespace ts {
|
||||
checkObjectTypeForDuplicateDeclarations(node);
|
||||
}
|
||||
forEach(getInterfaceBaseTypeNodes(node), heritageElement => {
|
||||
if (!isEntityNameExpression(heritageElement.expression)) {
|
||||
if (!isEntityNameExpression(heritageElement.expression) || isOptionalChain(heritageElement.expression)) {
|
||||
error(heritageElement.expression, Diagnostics.An_interface_can_only_extend_an_identifier_Slashqualified_name_with_optional_type_arguments);
|
||||
}
|
||||
checkTypeReferenceNode(heritageElement);
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
tests/cases/conformance/classes/classDeclarations/classHeritageSpecification/classExtendingOptionalChain.ts(9,21): error TS2500: A class can only implement an identifier/qualified-name with optional type arguments.
|
||||
|
||||
|
||||
==== tests/cases/conformance/classes/classDeclarations/classHeritageSpecification/classExtendingOptionalChain.ts (1 errors) ====
|
||||
namespace A {
|
||||
export class B {}
|
||||
}
|
||||
|
||||
// ok
|
||||
class C1 extends A?.B {}
|
||||
|
||||
// error
|
||||
class C2 implements A?.B {}
|
||||
~~~~
|
||||
!!! error TS2500: A class can only implement an identifier/qualified-name with optional type arguments.
|
||||
|
||||
51
tests/baselines/reference/classExtendingOptionalChain.js
Normal file
51
tests/baselines/reference/classExtendingOptionalChain.js
Normal file
@ -0,0 +1,51 @@
|
||||
//// [classExtendingOptionalChain.ts]
|
||||
namespace A {
|
||||
export class B {}
|
||||
}
|
||||
|
||||
// ok
|
||||
class C1 extends A?.B {}
|
||||
|
||||
// error
|
||||
class C2 implements A?.B {}
|
||||
|
||||
|
||||
//// [classExtendingOptionalChain.js]
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
if (typeof b !== "function" && b !== null)
|
||||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
var A;
|
||||
(function (A) {
|
||||
var B = /** @class */ (function () {
|
||||
function B() {
|
||||
}
|
||||
return B;
|
||||
}());
|
||||
A.B = B;
|
||||
})(A || (A = {}));
|
||||
// ok
|
||||
var C1 = /** @class */ (function (_super) {
|
||||
__extends(C1, _super);
|
||||
function C1() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
return C1;
|
||||
}((A === null || A === void 0 ? void 0 : A.B)));
|
||||
// error
|
||||
var C2 = /** @class */ (function () {
|
||||
function C2() {
|
||||
}
|
||||
return C2;
|
||||
}());
|
||||
@ -0,0 +1,22 @@
|
||||
=== tests/cases/conformance/classes/classDeclarations/classHeritageSpecification/classExtendingOptionalChain.ts ===
|
||||
namespace A {
|
||||
>A : Symbol(A, Decl(classExtendingOptionalChain.ts, 0, 0))
|
||||
|
||||
export class B {}
|
||||
>B : Symbol(B, Decl(classExtendingOptionalChain.ts, 0, 13))
|
||||
}
|
||||
|
||||
// ok
|
||||
class C1 extends A?.B {}
|
||||
>C1 : Symbol(C1, Decl(classExtendingOptionalChain.ts, 2, 1))
|
||||
>A?.B : Symbol(A.B, Decl(classExtendingOptionalChain.ts, 0, 13))
|
||||
>A : Symbol(A, Decl(classExtendingOptionalChain.ts, 0, 0))
|
||||
>B : Symbol(A.B, Decl(classExtendingOptionalChain.ts, 0, 13))
|
||||
|
||||
// error
|
||||
class C2 implements A?.B {}
|
||||
>C2 : Symbol(C2, Decl(classExtendingOptionalChain.ts, 5, 24))
|
||||
>A?.B : Symbol(A.B, Decl(classExtendingOptionalChain.ts, 0, 13))
|
||||
>A : Symbol(A, Decl(classExtendingOptionalChain.ts, 0, 0))
|
||||
>B : Symbol(A.B, Decl(classExtendingOptionalChain.ts, 0, 13))
|
||||
|
||||
20
tests/baselines/reference/classExtendingOptionalChain.types
Normal file
20
tests/baselines/reference/classExtendingOptionalChain.types
Normal file
@ -0,0 +1,20 @@
|
||||
=== tests/cases/conformance/classes/classDeclarations/classHeritageSpecification/classExtendingOptionalChain.ts ===
|
||||
namespace A {
|
||||
>A : typeof A
|
||||
|
||||
export class B {}
|
||||
>B : B
|
||||
}
|
||||
|
||||
// ok
|
||||
class C1 extends A?.B {}
|
||||
>C1 : C1
|
||||
>A?.B : A.B
|
||||
>A : typeof A
|
||||
>B : typeof A.B
|
||||
|
||||
// error
|
||||
class C2 implements A?.B {}
|
||||
>C2 : C2
|
||||
>A : typeof A
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendingOptionalChain.ts(5,22): error TS2499: An interface can only extend an identifier/qualified-name with optional type arguments.
|
||||
|
||||
|
||||
==== tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendingOptionalChain.ts (1 errors) ====
|
||||
namespace Foo {
|
||||
export class Bar {}
|
||||
}
|
||||
|
||||
interface C1 extends Foo?.Bar {}
|
||||
~~~~~~~~
|
||||
!!! error TS2499: An interface can only extend an identifier/qualified-name with optional type arguments.
|
||||
|
||||
18
tests/baselines/reference/interfaceExtendingOptionalChain.js
Normal file
18
tests/baselines/reference/interfaceExtendingOptionalChain.js
Normal file
@ -0,0 +1,18 @@
|
||||
//// [interfaceExtendingOptionalChain.ts]
|
||||
namespace Foo {
|
||||
export class Bar {}
|
||||
}
|
||||
|
||||
interface C1 extends Foo?.Bar {}
|
||||
|
||||
|
||||
//// [interfaceExtendingOptionalChain.js]
|
||||
var Foo;
|
||||
(function (Foo) {
|
||||
var Bar = /** @class */ (function () {
|
||||
function Bar() {
|
||||
}
|
||||
return Bar;
|
||||
}());
|
||||
Foo.Bar = Bar;
|
||||
})(Foo || (Foo = {}));
|
||||
@ -0,0 +1,14 @@
|
||||
=== tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendingOptionalChain.ts ===
|
||||
namespace Foo {
|
||||
>Foo : Symbol(Foo, Decl(interfaceExtendingOptionalChain.ts, 0, 0))
|
||||
|
||||
export class Bar {}
|
||||
>Bar : Symbol(Bar, Decl(interfaceExtendingOptionalChain.ts, 0, 15))
|
||||
}
|
||||
|
||||
interface C1 extends Foo?.Bar {}
|
||||
>C1 : Symbol(C1, Decl(interfaceExtendingOptionalChain.ts, 2, 1))
|
||||
>Foo?.Bar : Symbol(Foo.Bar, Decl(interfaceExtendingOptionalChain.ts, 0, 15))
|
||||
>Foo : Symbol(Foo, Decl(interfaceExtendingOptionalChain.ts, 0, 0))
|
||||
>Bar : Symbol(Foo.Bar, Decl(interfaceExtendingOptionalChain.ts, 0, 15))
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
=== tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendingOptionalChain.ts ===
|
||||
namespace Foo {
|
||||
>Foo : typeof Foo
|
||||
|
||||
export class Bar {}
|
||||
>Bar : Bar
|
||||
}
|
||||
|
||||
interface C1 extends Foo?.Bar {}
|
||||
>Foo : typeof Foo
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
namespace A {
|
||||
export class B {}
|
||||
}
|
||||
|
||||
// ok
|
||||
class C1 extends A?.B {}
|
||||
|
||||
// error
|
||||
class C2 implements A?.B {}
|
||||
@ -0,0 +1,5 @@
|
||||
namespace Foo {
|
||||
export class Bar {}
|
||||
}
|
||||
|
||||
interface C1 extends Foo?.Bar {}
|
||||
Loading…
x
Reference in New Issue
Block a user