mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 08:11:30 -06:00
Allow multiple class base types; intersect them, as with interfaces (#23123)
This commit is contained in:
parent
a4593fd6db
commit
78ba32a110
@ -16509,26 +16509,25 @@ namespace ts {
|
||||
if (!(prop.parent.flags & SymbolFlags.Class)) {
|
||||
return false;
|
||||
}
|
||||
let classType = getTypeOfSymbol(prop.parent) as InterfaceType;
|
||||
let classType = getTypeOfSymbol(prop.parent);
|
||||
while (true) {
|
||||
classType = getSuperClass(classType);
|
||||
classType = classType.symbol && getSuperClass(classType as InterfaceType);
|
||||
if (!classType) {
|
||||
return false;
|
||||
}
|
||||
const superProperty = getPropertyOfObjectType(classType, prop.escapedName);
|
||||
const superProperty = getPropertyOfType(classType, prop.escapedName);
|
||||
if (superProperty && superProperty.valueDeclaration) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getSuperClass(classType: InterfaceType): InterfaceType | undefined {
|
||||
function getSuperClass(classType: InterfaceType): Type | undefined {
|
||||
const x = getBaseTypes(classType);
|
||||
if (x.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
Debug.assert(x.length === 1);
|
||||
return x[0] as InterfaceType;
|
||||
return getIntersectionType(x);
|
||||
}
|
||||
|
||||
function reportNonexistentProperty(propNode: Identifier, containingType: Type) {
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
tests/cases/compiler/classMergedWithInterfaceMultipleBasesNoError.ts(8,30): error TS2448: Block-scoped variable 'handleIntersection' used before its declaration.
|
||||
|
||||
|
||||
==== tests/cases/compiler/classMergedWithInterfaceMultipleBasesNoError.ts (1 errors) ====
|
||||
interface Bar { }
|
||||
interface Baz { }
|
||||
interface Q { }
|
||||
interface Foo extends Bar, Baz { }
|
||||
class Foo { }
|
||||
|
||||
export default class extends Foo {
|
||||
readonly observer = this.handleIntersection;
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2448: Block-scoped variable 'handleIntersection' used before its declaration.
|
||||
readonly handleIntersection = () => { }
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
//// [classMergedWithInterfaceMultipleBasesNoError.ts]
|
||||
interface Bar { }
|
||||
interface Baz { }
|
||||
interface Q { }
|
||||
interface Foo extends Bar, Baz { }
|
||||
class Foo { }
|
||||
|
||||
export default class extends Foo {
|
||||
readonly observer = this.handleIntersection;
|
||||
readonly handleIntersection = () => { }
|
||||
}
|
||||
|
||||
//// [classMergedWithInterfaceMultipleBasesNoError.js]
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
exports.__esModule = true;
|
||||
var Foo = /** @class */ (function () {
|
||||
function Foo() {
|
||||
}
|
||||
return Foo;
|
||||
}());
|
||||
var default_1 = /** @class */ (function (_super) {
|
||||
__extends(default_1, _super);
|
||||
function default_1() {
|
||||
var _this = _super !== null && _super.apply(this, arguments) || this;
|
||||
_this.observer = _this.handleIntersection;
|
||||
_this.handleIntersection = function () { };
|
||||
return _this;
|
||||
}
|
||||
return default_1;
|
||||
}(Foo));
|
||||
exports["default"] = default_1;
|
||||
@ -0,0 +1,30 @@
|
||||
=== tests/cases/compiler/classMergedWithInterfaceMultipleBasesNoError.ts ===
|
||||
interface Bar { }
|
||||
>Bar : Symbol(Bar, Decl(classMergedWithInterfaceMultipleBasesNoError.ts, 0, 0))
|
||||
|
||||
interface Baz { }
|
||||
>Baz : Symbol(Baz, Decl(classMergedWithInterfaceMultipleBasesNoError.ts, 0, 17))
|
||||
|
||||
interface Q { }
|
||||
>Q : Symbol(Q, Decl(classMergedWithInterfaceMultipleBasesNoError.ts, 1, 17))
|
||||
|
||||
interface Foo extends Bar, Baz { }
|
||||
>Foo : Symbol(Foo, Decl(classMergedWithInterfaceMultipleBasesNoError.ts, 2, 15), Decl(classMergedWithInterfaceMultipleBasesNoError.ts, 3, 34))
|
||||
>Bar : Symbol(Bar, Decl(classMergedWithInterfaceMultipleBasesNoError.ts, 0, 0))
|
||||
>Baz : Symbol(Baz, Decl(classMergedWithInterfaceMultipleBasesNoError.ts, 0, 17))
|
||||
|
||||
class Foo { }
|
||||
>Foo : Symbol(Foo, Decl(classMergedWithInterfaceMultipleBasesNoError.ts, 2, 15), Decl(classMergedWithInterfaceMultipleBasesNoError.ts, 3, 34))
|
||||
|
||||
export default class extends Foo {
|
||||
>Foo : Symbol(Foo, Decl(classMergedWithInterfaceMultipleBasesNoError.ts, 2, 15), Decl(classMergedWithInterfaceMultipleBasesNoError.ts, 3, 34))
|
||||
|
||||
readonly observer = this.handleIntersection;
|
||||
>observer : Symbol(default.observer, Decl(classMergedWithInterfaceMultipleBasesNoError.ts, 6, 34))
|
||||
>this.handleIntersection : Symbol(default.handleIntersection, Decl(classMergedWithInterfaceMultipleBasesNoError.ts, 7, 48))
|
||||
>this : Symbol(default, Decl(classMergedWithInterfaceMultipleBasesNoError.ts, 4, 13))
|
||||
>handleIntersection : Symbol(default.handleIntersection, Decl(classMergedWithInterfaceMultipleBasesNoError.ts, 7, 48))
|
||||
|
||||
readonly handleIntersection = () => { }
|
||||
>handleIntersection : Symbol(default.handleIntersection, Decl(classMergedWithInterfaceMultipleBasesNoError.ts, 7, 48))
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
=== tests/cases/compiler/classMergedWithInterfaceMultipleBasesNoError.ts ===
|
||||
interface Bar { }
|
||||
>Bar : Bar
|
||||
|
||||
interface Baz { }
|
||||
>Baz : Baz
|
||||
|
||||
interface Q { }
|
||||
>Q : Q
|
||||
|
||||
interface Foo extends Bar, Baz { }
|
||||
>Foo : Foo
|
||||
>Bar : Bar
|
||||
>Baz : Baz
|
||||
|
||||
class Foo { }
|
||||
>Foo : Foo
|
||||
|
||||
export default class extends Foo {
|
||||
>Foo : Foo
|
||||
|
||||
readonly observer = this.handleIntersection;
|
||||
>observer : () => void
|
||||
>this.handleIntersection : () => void
|
||||
>this : this
|
||||
>handleIntersection : () => void
|
||||
|
||||
readonly handleIntersection = () => { }
|
||||
>handleIntersection : () => void
|
||||
>() => { } : () => void
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
interface Bar { }
|
||||
interface Baz { }
|
||||
interface Q { }
|
||||
interface Foo extends Bar, Baz { }
|
||||
class Foo { }
|
||||
|
||||
export default class extends Foo {
|
||||
readonly observer = this.handleIntersection;
|
||||
readonly handleIntersection = () => { }
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user