mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-10 15:25:54 -06:00
Merge pull request #14635 from Microsoft/fixIntersectionMethodOverrides
Fix intersection method overrides
This commit is contained in:
commit
363c5144bc
@ -5129,7 +5129,8 @@ namespace ts {
|
||||
const excludeModifiers = isUnion ? ModifierFlags.NonPublicAccessibilityModifier : 0;
|
||||
// Flags we want to propagate to the result if they exist in all source symbols
|
||||
let commonFlags = isUnion ? SymbolFlags.None : SymbolFlags.Optional;
|
||||
let checkFlags = CheckFlags.SyntheticProperty;
|
||||
let syntheticFlag = CheckFlags.SyntheticMethod;
|
||||
let checkFlags = 0;
|
||||
for (const current of types) {
|
||||
const type = getApparentType(current);
|
||||
if (type !== unknownType) {
|
||||
@ -5148,6 +5149,9 @@ namespace ts {
|
||||
(modifiers & ModifierFlags.Protected ? CheckFlags.ContainsProtected : 0) |
|
||||
(modifiers & ModifierFlags.Private ? CheckFlags.ContainsPrivate : 0) |
|
||||
(modifiers & ModifierFlags.Static ? CheckFlags.ContainsStatic : 0);
|
||||
if (!isMethodLike(prop)) {
|
||||
syntheticFlag = CheckFlags.SyntheticProperty;
|
||||
}
|
||||
}
|
||||
else if (isUnion) {
|
||||
checkFlags |= CheckFlags.Partial;
|
||||
@ -5177,7 +5181,7 @@ namespace ts {
|
||||
propTypes.push(type);
|
||||
}
|
||||
const result = createSymbol(SymbolFlags.Property | commonFlags, name);
|
||||
result.checkFlags = checkFlags;
|
||||
result.checkFlags = syntheticFlag | checkFlags;
|
||||
result.containingType = containingType;
|
||||
result.declarations = declarations;
|
||||
result.type = isUnion ? getUnionType(propTypes) : getIntersectionType(propTypes);
|
||||
@ -8630,7 +8634,7 @@ namespace ts {
|
||||
// Invoke the callback for each underlying property symbol of the given symbol and return the first
|
||||
// value that isn't undefined.
|
||||
function forEachProperty<T>(prop: Symbol, callback: (p: Symbol) => T): T {
|
||||
if (getCheckFlags(prop) & CheckFlags.SyntheticProperty) {
|
||||
if (getCheckFlags(prop) & CheckFlags.Synthetic) {
|
||||
for (const t of (<TransientSymbol>prop).containingType.types) {
|
||||
const p = getPropertyOfType(t, prop.name);
|
||||
const result = p && forEachProperty(p, callback);
|
||||
@ -13112,7 +13116,7 @@ namespace ts {
|
||||
const flags = getCombinedModifierFlags(s.valueDeclaration);
|
||||
return s.parent && s.parent.flags & SymbolFlags.Class ? flags : flags & ~ModifierFlags.AccessibilityModifier;
|
||||
}
|
||||
if (getCheckFlags(s) & CheckFlags.SyntheticProperty) {
|
||||
if (getCheckFlags(s) & CheckFlags.Synthetic) {
|
||||
const checkFlags = (<TransientSymbol>s).checkFlags;
|
||||
const accessModifier = checkFlags & CheckFlags.ContainsPrivate ? ModifierFlags.Private :
|
||||
checkFlags & CheckFlags.ContainsPublic ? ModifierFlags.Public :
|
||||
@ -13130,6 +13134,10 @@ namespace ts {
|
||||
return s.valueDeclaration ? getCombinedNodeFlags(s.valueDeclaration) : 0;
|
||||
}
|
||||
|
||||
function isMethodLike(symbol: Symbol) {
|
||||
return !!(symbol.flags & SymbolFlags.Method || getCheckFlags(symbol) & CheckFlags.SyntheticMethod);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the requested property access is valid.
|
||||
* Returns true if node is a valid property access, and false otherwise.
|
||||
@ -13159,11 +13167,11 @@ namespace ts {
|
||||
// where this references the constructor function object of a derived class,
|
||||
// a super property access is permitted and must specify a public static member function of the base class.
|
||||
if (languageVersion < ScriptTarget.ES2015) {
|
||||
const propKind = getDeclarationKindFromSymbol(prop);
|
||||
if (propKind !== SyntaxKind.MethodDeclaration && propKind !== SyntaxKind.MethodSignature) {
|
||||
// `prop` refers to a *property* declared in the super class
|
||||
// rather than a *method*, so it does not satisfy the above criteria.
|
||||
|
||||
const hasNonMethodDeclaration = forEachProperty(prop, p => {
|
||||
const propKind = getDeclarationKindFromSymbol(p);
|
||||
return propKind !== SyntaxKind.MethodDeclaration && propKind !== SyntaxKind.MethodSignature;
|
||||
});
|
||||
if (hasNonMethodDeclaration) {
|
||||
error(errorNode, Diagnostics.Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword);
|
||||
return false;
|
||||
}
|
||||
@ -19697,7 +19705,7 @@ namespace ts {
|
||||
else {
|
||||
// derived overrides base.
|
||||
const derivedDeclarationFlags = getDeclarationModifierFlagsFromSymbol(derived);
|
||||
if ((baseDeclarationFlags & ModifierFlags.Private) || (derivedDeclarationFlags & ModifierFlags.Private)) {
|
||||
if (baseDeclarationFlags & ModifierFlags.Private || derivedDeclarationFlags & ModifierFlags.Private) {
|
||||
// either base or derived property is private - not override, skip it
|
||||
continue;
|
||||
}
|
||||
@ -19707,28 +19715,24 @@ namespace ts {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((base.flags & derived.flags & SymbolFlags.Method) || ((base.flags & SymbolFlags.PropertyOrAccessor) && (derived.flags & SymbolFlags.PropertyOrAccessor))) {
|
||||
if (isMethodLike(base) && isMethodLike(derived) || base.flags & SymbolFlags.PropertyOrAccessor && derived.flags & SymbolFlags.PropertyOrAccessor) {
|
||||
// method is overridden with method or property/accessor is overridden with property/accessor - correct case
|
||||
continue;
|
||||
}
|
||||
|
||||
let errorMessage: DiagnosticMessage;
|
||||
if (base.flags & SymbolFlags.Method) {
|
||||
if (isMethodLike(base)) {
|
||||
if (derived.flags & SymbolFlags.Accessor) {
|
||||
errorMessage = Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor;
|
||||
}
|
||||
else {
|
||||
Debug.assert((derived.flags & SymbolFlags.Property) !== 0);
|
||||
errorMessage = Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_property;
|
||||
}
|
||||
}
|
||||
else if (base.flags & SymbolFlags.Property) {
|
||||
Debug.assert((derived.flags & SymbolFlags.Method) !== 0);
|
||||
errorMessage = Diagnostics.Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_function;
|
||||
}
|
||||
else {
|
||||
Debug.assert((base.flags & SymbolFlags.Accessor) !== 0);
|
||||
Debug.assert((derived.flags & SymbolFlags.Method) !== 0);
|
||||
errorMessage = Diagnostics.Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function;
|
||||
}
|
||||
|
||||
@ -21387,7 +21391,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getRootSymbols(symbol: Symbol): Symbol[] {
|
||||
if (getCheckFlags(symbol) & CheckFlags.SyntheticProperty) {
|
||||
if (getCheckFlags(symbol) & CheckFlags.Synthetic) {
|
||||
const symbols: Symbol[] = [];
|
||||
const name = symbol.name;
|
||||
forEach(getSymbolLinks(symbol).containingType.types, t => {
|
||||
|
||||
@ -2825,13 +2825,15 @@ namespace ts {
|
||||
export const enum CheckFlags {
|
||||
Instantiated = 1 << 0, // Instantiated symbol
|
||||
SyntheticProperty = 1 << 1, // Property in union or intersection type
|
||||
Readonly = 1 << 2, // Readonly transient symbol
|
||||
Partial = 1 << 3, // Synthetic property present in some but not all constituents
|
||||
HasNonUniformType = 1 << 4, // Synthetic property with non-uniform type in constituents
|
||||
ContainsPublic = 1 << 5, // Synthetic property with public constituent(s)
|
||||
ContainsProtected = 1 << 6, // Synthetic property with protected constituent(s)
|
||||
ContainsPrivate = 1 << 7, // Synthetic property with private constituent(s)
|
||||
ContainsStatic = 1 << 8, // Synthetic property with static constituent(s)
|
||||
SyntheticMethod = 1 << 2, // Method in union or intersection type
|
||||
Readonly = 1 << 3, // Readonly transient symbol
|
||||
Partial = 1 << 4, // Synthetic property present in some but not all constituents
|
||||
HasNonUniformType = 1 << 5, // Synthetic property with non-uniform type in constituents
|
||||
ContainsPublic = 1 << 6, // Synthetic property with public constituent(s)
|
||||
ContainsProtected = 1 << 7, // Synthetic property with protected constituent(s)
|
||||
ContainsPrivate = 1 << 8, // Synthetic property with private constituent(s)
|
||||
ContainsStatic = 1 << 9, // Synthetic property with static constituent(s)
|
||||
Synthetic = SyntheticProperty | SyntheticMethod
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
||||
@ -335,7 +335,7 @@ namespace ts.FindAllReferences {
|
||||
|
||||
// if this symbol is visible from its parent container, e.g. exported, then bail out
|
||||
// if symbol correspond to the union property - bail out
|
||||
if (symbol.parent || (symbol.flags & SymbolFlags.Transient && (<TransientSymbol>symbol).checkFlags & CheckFlags.SyntheticProperty)) {
|
||||
if (symbol.parent || (symbol.flags & SymbolFlags.Transient && (<TransientSymbol>symbol).checkFlags & CheckFlags.Synthetic)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
@ -52,7 +52,7 @@ namespace ts.SymbolDisplay {
|
||||
if (flags & SymbolFlags.Constructor) return ScriptElementKind.constructorImplementationElement;
|
||||
|
||||
if (flags & SymbolFlags.Property) {
|
||||
if (flags & SymbolFlags.Transient && (<TransientSymbol>symbol).checkFlags & CheckFlags.SyntheticProperty) {
|
||||
if (flags & SymbolFlags.Transient && (<TransientSymbol>symbol).checkFlags & CheckFlags.Synthetic) {
|
||||
// If union property is result of union of non method (property/accessors/variables), it is labeled as property
|
||||
const unionPropertyKind = forEach(typeChecker.getRootSymbols(symbol), rootSymbol => {
|
||||
const rootSymbolFlags = rootSymbol.getFlags();
|
||||
|
||||
83
tests/baselines/reference/overrideBaseIntersectionMethod.js
Normal file
83
tests/baselines/reference/overrideBaseIntersectionMethod.js
Normal file
@ -0,0 +1,83 @@
|
||||
//// [overrideBaseIntersectionMethod.ts]
|
||||
|
||||
// Repro from #14615
|
||||
|
||||
type Constructor<T> = new (...args: any[]) => T;
|
||||
|
||||
const WithLocation = <T extends Constructor<Point>>(Base: T) => class extends Base {
|
||||
getLocation(): [number, number] {
|
||||
const [x,y] = super.getLocation();
|
||||
return [this.x | x, this.y | y];
|
||||
}
|
||||
}
|
||||
|
||||
class Point {
|
||||
constructor(public x: number, public y: number) { }
|
||||
getLocation(): [number, number] {
|
||||
return [0,0];
|
||||
}
|
||||
}
|
||||
|
||||
class Foo extends WithLocation(Point) {
|
||||
calculate() {
|
||||
return this.x + this.y;
|
||||
}
|
||||
getLocation() {
|
||||
return super.getLocation()
|
||||
}
|
||||
whereAmI() {
|
||||
return this.getLocation();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// [overrideBaseIntersectionMethod.js]
|
||||
// Repro from #14615
|
||||
"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 __());
|
||||
};
|
||||
})();
|
||||
var WithLocation = function (Base) { return (function (_super) {
|
||||
__extends(class_1, _super);
|
||||
function class_1() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
class_1.prototype.getLocation = function () {
|
||||
var _a = _super.prototype.getLocation.call(this), x = _a[0], y = _a[1];
|
||||
return [this.x | x, this.y | y];
|
||||
};
|
||||
return class_1;
|
||||
}(Base)); };
|
||||
var Point = (function () {
|
||||
function Point(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
Point.prototype.getLocation = function () {
|
||||
return [0, 0];
|
||||
};
|
||||
return Point;
|
||||
}());
|
||||
var Foo = (function (_super) {
|
||||
__extends(Foo, _super);
|
||||
function Foo() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
Foo.prototype.calculate = function () {
|
||||
return this.x + this.y;
|
||||
};
|
||||
Foo.prototype.getLocation = function () {
|
||||
return _super.prototype.getLocation.call(this);
|
||||
};
|
||||
Foo.prototype.whereAmI = function () {
|
||||
return this.getLocation();
|
||||
};
|
||||
return Foo;
|
||||
}(WithLocation(Point)));
|
||||
@ -0,0 +1,88 @@
|
||||
=== tests/cases/compiler/overrideBaseIntersectionMethod.ts ===
|
||||
|
||||
// Repro from #14615
|
||||
|
||||
type Constructor<T> = new (...args: any[]) => T;
|
||||
>Constructor : Symbol(Constructor, Decl(overrideBaseIntersectionMethod.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(overrideBaseIntersectionMethod.ts, 3, 17))
|
||||
>args : Symbol(args, Decl(overrideBaseIntersectionMethod.ts, 3, 27))
|
||||
>T : Symbol(T, Decl(overrideBaseIntersectionMethod.ts, 3, 17))
|
||||
|
||||
const WithLocation = <T extends Constructor<Point>>(Base: T) => class extends Base {
|
||||
>WithLocation : Symbol(WithLocation, Decl(overrideBaseIntersectionMethod.ts, 5, 5))
|
||||
>T : Symbol(T, Decl(overrideBaseIntersectionMethod.ts, 5, 22))
|
||||
>Constructor : Symbol(Constructor, Decl(overrideBaseIntersectionMethod.ts, 0, 0))
|
||||
>Point : Symbol(Point, Decl(overrideBaseIntersectionMethod.ts, 10, 1))
|
||||
>Base : Symbol(Base, Decl(overrideBaseIntersectionMethod.ts, 5, 52))
|
||||
>T : Symbol(T, Decl(overrideBaseIntersectionMethod.ts, 5, 22))
|
||||
>Base : Symbol(Base, Decl(overrideBaseIntersectionMethod.ts, 5, 52))
|
||||
|
||||
getLocation(): [number, number] {
|
||||
>getLocation : Symbol((Anonymous class).getLocation, Decl(overrideBaseIntersectionMethod.ts, 5, 84))
|
||||
|
||||
const [x,y] = super.getLocation();
|
||||
>x : Symbol(x, Decl(overrideBaseIntersectionMethod.ts, 7, 11))
|
||||
>y : Symbol(y, Decl(overrideBaseIntersectionMethod.ts, 7, 13))
|
||||
>super.getLocation : Symbol(Point.getLocation, Decl(overrideBaseIntersectionMethod.ts, 13, 53))
|
||||
>super : Symbol(Point, Decl(overrideBaseIntersectionMethod.ts, 10, 1))
|
||||
>getLocation : Symbol(Point.getLocation, Decl(overrideBaseIntersectionMethod.ts, 13, 53))
|
||||
|
||||
return [this.x | x, this.y | y];
|
||||
>this.x : Symbol(Point.x, Decl(overrideBaseIntersectionMethod.ts, 13, 14))
|
||||
>this : Symbol((Anonymous class), Decl(overrideBaseIntersectionMethod.ts, 5, 63))
|
||||
>x : Symbol(Point.x, Decl(overrideBaseIntersectionMethod.ts, 13, 14))
|
||||
>x : Symbol(x, Decl(overrideBaseIntersectionMethod.ts, 7, 11))
|
||||
>this.y : Symbol(Point.y, Decl(overrideBaseIntersectionMethod.ts, 13, 31))
|
||||
>this : Symbol((Anonymous class), Decl(overrideBaseIntersectionMethod.ts, 5, 63))
|
||||
>y : Symbol(Point.y, Decl(overrideBaseIntersectionMethod.ts, 13, 31))
|
||||
>y : Symbol(y, Decl(overrideBaseIntersectionMethod.ts, 7, 13))
|
||||
}
|
||||
}
|
||||
|
||||
class Point {
|
||||
>Point : Symbol(Point, Decl(overrideBaseIntersectionMethod.ts, 10, 1))
|
||||
|
||||
constructor(public x: number, public y: number) { }
|
||||
>x : Symbol(Point.x, Decl(overrideBaseIntersectionMethod.ts, 13, 14))
|
||||
>y : Symbol(Point.y, Decl(overrideBaseIntersectionMethod.ts, 13, 31))
|
||||
|
||||
getLocation(): [number, number] {
|
||||
>getLocation : Symbol(Point.getLocation, Decl(overrideBaseIntersectionMethod.ts, 13, 53))
|
||||
|
||||
return [0,0];
|
||||
}
|
||||
}
|
||||
|
||||
class Foo extends WithLocation(Point) {
|
||||
>Foo : Symbol(Foo, Decl(overrideBaseIntersectionMethod.ts, 17, 1))
|
||||
>WithLocation : Symbol(WithLocation, Decl(overrideBaseIntersectionMethod.ts, 5, 5))
|
||||
>Point : Symbol(Point, Decl(overrideBaseIntersectionMethod.ts, 10, 1))
|
||||
|
||||
calculate() {
|
||||
>calculate : Symbol(Foo.calculate, Decl(overrideBaseIntersectionMethod.ts, 19, 39))
|
||||
|
||||
return this.x + this.y;
|
||||
>this.x : Symbol(Point.x, Decl(overrideBaseIntersectionMethod.ts, 13, 14))
|
||||
>this : Symbol(Foo, Decl(overrideBaseIntersectionMethod.ts, 17, 1))
|
||||
>x : Symbol(Point.x, Decl(overrideBaseIntersectionMethod.ts, 13, 14))
|
||||
>this.y : Symbol(Point.y, Decl(overrideBaseIntersectionMethod.ts, 13, 31))
|
||||
>this : Symbol(Foo, Decl(overrideBaseIntersectionMethod.ts, 17, 1))
|
||||
>y : Symbol(Point.y, Decl(overrideBaseIntersectionMethod.ts, 13, 31))
|
||||
}
|
||||
getLocation() {
|
||||
>getLocation : Symbol(Foo.getLocation, Decl(overrideBaseIntersectionMethod.ts, 22, 3))
|
||||
|
||||
return super.getLocation()
|
||||
>super.getLocation : Symbol(getLocation, Decl(overrideBaseIntersectionMethod.ts, 5, 84), Decl(overrideBaseIntersectionMethod.ts, 13, 53))
|
||||
>getLocation : Symbol(getLocation, Decl(overrideBaseIntersectionMethod.ts, 5, 84), Decl(overrideBaseIntersectionMethod.ts, 13, 53))
|
||||
}
|
||||
whereAmI() {
|
||||
>whereAmI : Symbol(Foo.whereAmI, Decl(overrideBaseIntersectionMethod.ts, 25, 3))
|
||||
|
||||
return this.getLocation();
|
||||
>this.getLocation : Symbol(Foo.getLocation, Decl(overrideBaseIntersectionMethod.ts, 22, 3))
|
||||
>this : Symbol(Foo, Decl(overrideBaseIntersectionMethod.ts, 17, 1))
|
||||
>getLocation : Symbol(Foo.getLocation, Decl(overrideBaseIntersectionMethod.ts, 22, 3))
|
||||
}
|
||||
}
|
||||
|
||||
102
tests/baselines/reference/overrideBaseIntersectionMethod.types
Normal file
102
tests/baselines/reference/overrideBaseIntersectionMethod.types
Normal file
@ -0,0 +1,102 @@
|
||||
=== tests/cases/compiler/overrideBaseIntersectionMethod.ts ===
|
||||
|
||||
// Repro from #14615
|
||||
|
||||
type Constructor<T> = new (...args: any[]) => T;
|
||||
>Constructor : Constructor<T>
|
||||
>T : T
|
||||
>args : any[]
|
||||
>T : T
|
||||
|
||||
const WithLocation = <T extends Constructor<Point>>(Base: T) => class extends Base {
|
||||
>WithLocation : <T extends Constructor<Point>>(Base: T) => { new (...args: any[]): (Anonymous class); prototype: <any>.(Anonymous class); } & T
|
||||
><T extends Constructor<Point>>(Base: T) => class extends Base { getLocation(): [number, number] { const [x,y] = super.getLocation(); return [this.x | x, this.y | y]; }} : <T extends Constructor<Point>>(Base: T) => { new (...args: any[]): (Anonymous class); prototype: <any>.(Anonymous class); } & T
|
||||
>T : T
|
||||
>Constructor : Constructor<T>
|
||||
>Point : Point
|
||||
>Base : T
|
||||
>T : T
|
||||
>class extends Base { getLocation(): [number, number] { const [x,y] = super.getLocation(); return [this.x | x, this.y | y]; }} : { new (...args: any[]): (Anonymous class); prototype: <any>.(Anonymous class); } & T
|
||||
>Base : Point
|
||||
|
||||
getLocation(): [number, number] {
|
||||
>getLocation : () => [number, number]
|
||||
|
||||
const [x,y] = super.getLocation();
|
||||
>x : number
|
||||
>y : number
|
||||
>super.getLocation() : [number, number]
|
||||
>super.getLocation : () => [number, number]
|
||||
>super : Point
|
||||
>getLocation : () => [number, number]
|
||||
|
||||
return [this.x | x, this.y | y];
|
||||
>[this.x | x, this.y | y] : [number, number]
|
||||
>this.x | x : number
|
||||
>this.x : number
|
||||
>this : this
|
||||
>x : number
|
||||
>x : number
|
||||
>this.y | y : number
|
||||
>this.y : number
|
||||
>this : this
|
||||
>y : number
|
||||
>y : number
|
||||
}
|
||||
}
|
||||
|
||||
class Point {
|
||||
>Point : Point
|
||||
|
||||
constructor(public x: number, public y: number) { }
|
||||
>x : number
|
||||
>y : number
|
||||
|
||||
getLocation(): [number, number] {
|
||||
>getLocation : () => [number, number]
|
||||
|
||||
return [0,0];
|
||||
>[0,0] : [number, number]
|
||||
>0 : 0
|
||||
>0 : 0
|
||||
}
|
||||
}
|
||||
|
||||
class Foo extends WithLocation(Point) {
|
||||
>Foo : Foo
|
||||
>WithLocation(Point) : <typeof Point>.(Anonymous class) & Point
|
||||
>WithLocation : <T extends Constructor<Point>>(Base: T) => { new (...args: any[]): (Anonymous class); prototype: <any>.(Anonymous class); } & T
|
||||
>Point : typeof Point
|
||||
|
||||
calculate() {
|
||||
>calculate : () => number
|
||||
|
||||
return this.x + this.y;
|
||||
>this.x + this.y : number
|
||||
>this.x : number
|
||||
>this : this
|
||||
>x : number
|
||||
>this.y : number
|
||||
>this : this
|
||||
>y : number
|
||||
}
|
||||
getLocation() {
|
||||
>getLocation : () => [number, number]
|
||||
|
||||
return super.getLocation()
|
||||
>super.getLocation() : [number, number]
|
||||
>super.getLocation : () => [number, number]
|
||||
>super : <typeof Point>.(Anonymous class) & Point
|
||||
>getLocation : () => [number, number]
|
||||
}
|
||||
whereAmI() {
|
||||
>whereAmI : () => [number, number]
|
||||
|
||||
return this.getLocation();
|
||||
>this.getLocation() : [number, number]
|
||||
>this.getLocation : () => [number, number]
|
||||
>this : this
|
||||
>getLocation : () => [number, number]
|
||||
}
|
||||
}
|
||||
|
||||
31
tests/cases/compiler/overrideBaseIntersectionMethod.ts
Normal file
31
tests/cases/compiler/overrideBaseIntersectionMethod.ts
Normal file
@ -0,0 +1,31 @@
|
||||
// @strict: true
|
||||
|
||||
// Repro from #14615
|
||||
|
||||
type Constructor<T> = new (...args: any[]) => T;
|
||||
|
||||
const WithLocation = <T extends Constructor<Point>>(Base: T) => class extends Base {
|
||||
getLocation(): [number, number] {
|
||||
const [x,y] = super.getLocation();
|
||||
return [this.x | x, this.y | y];
|
||||
}
|
||||
}
|
||||
|
||||
class Point {
|
||||
constructor(public x: number, public y: number) { }
|
||||
getLocation(): [number, number] {
|
||||
return [0,0];
|
||||
}
|
||||
}
|
||||
|
||||
class Foo extends WithLocation(Point) {
|
||||
calculate() {
|
||||
return this.x + this.y;
|
||||
}
|
||||
getLocation() {
|
||||
return super.getLocation()
|
||||
}
|
||||
whereAmI() {
|
||||
return this.getLocation();
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user