mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-10 18:04:18 -05:00
Skip base type checks that can cause circularities (#44615)
* Don't do base type checks that can cause circularities * Add regression tests
This commit is contained in:
@@ -20082,6 +20082,14 @@ namespace ts {
|
||||
}
|
||||
(type as TypeReference).objectFlags |= ObjectFlags.IdenticalBaseTypeCalculated;
|
||||
const target = (type as TypeReference).target as InterfaceType;
|
||||
if (getObjectFlags(target) & ObjectFlags.Class) {
|
||||
const baseTypeNode = getBaseTypeNodeOfClass(target);
|
||||
// A base type expression may circularly reference the class itself (e.g. as an argument to function call), so we only
|
||||
// check for base types specified as simple qualified names.
|
||||
if (baseTypeNode && baseTypeNode.expression.kind !== SyntaxKind.Identifier && baseTypeNode.expression.kind !== SyntaxKind.PropertyAccessExpression) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
const bases = getBaseTypes(target);
|
||||
if (bases.length !== 1) {
|
||||
return undefined;
|
||||
|
||||
92
tests/baselines/reference/recursiveClassBaseType.js
Normal file
92
tests/baselines/reference/recursiveClassBaseType.js
Normal file
@@ -0,0 +1,92 @@
|
||||
//// [recursiveClassBaseType.ts]
|
||||
// Repro from #44281
|
||||
|
||||
declare const p: <T>(fn: () => T) => T;
|
||||
|
||||
declare const Base: <T>(val: T) => { new(): T };
|
||||
|
||||
class C extends Base({ x: p<C[]>(() => []) }) { }
|
||||
|
||||
// Repro from #44359
|
||||
|
||||
abstract class Base1 {
|
||||
abstract root(): Derived1;
|
||||
}
|
||||
|
||||
class Derived1 extends class extends Base1 {
|
||||
root() {
|
||||
return undefined as any;
|
||||
}
|
||||
}
|
||||
{ }
|
||||
|
||||
|
||||
//// [recursiveClassBaseType.js]
|
||||
"use strict";
|
||||
// Repro from #44281
|
||||
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 C = /** @class */ (function (_super) {
|
||||
__extends(C, _super);
|
||||
function C() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
return C;
|
||||
}(Base({ x: p(function () { return []; }) })));
|
||||
// Repro from #44359
|
||||
var Base1 = /** @class */ (function () {
|
||||
function Base1() {
|
||||
}
|
||||
return Base1;
|
||||
}());
|
||||
var Derived1 = /** @class */ (function (_super) {
|
||||
__extends(Derived1, _super);
|
||||
function Derived1() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
return Derived1;
|
||||
}(/** @class */ (function (_super) {
|
||||
__extends(class_1, _super);
|
||||
function class_1() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
class_1.prototype.root = function () {
|
||||
return undefined;
|
||||
};
|
||||
return class_1;
|
||||
}(Base1))));
|
||||
|
||||
|
||||
//// [recursiveClassBaseType.d.ts]
|
||||
declare const p: <T>(fn: () => T) => T;
|
||||
declare const Base: <T>(val: T) => {
|
||||
new (): T;
|
||||
};
|
||||
declare const C_base: new () => {
|
||||
x: C[];
|
||||
};
|
||||
declare class C extends C_base {
|
||||
}
|
||||
declare abstract class Base1 {
|
||||
abstract root(): Derived1;
|
||||
}
|
||||
declare const Derived1_base: {
|
||||
new (): {
|
||||
root(): any;
|
||||
};
|
||||
};
|
||||
declare class Derived1 extends Derived1_base {
|
||||
}
|
||||
47
tests/baselines/reference/recursiveClassBaseType.symbols
Normal file
47
tests/baselines/reference/recursiveClassBaseType.symbols
Normal file
@@ -0,0 +1,47 @@
|
||||
=== tests/cases/compiler/recursiveClassBaseType.ts ===
|
||||
// Repro from #44281
|
||||
|
||||
declare const p: <T>(fn: () => T) => T;
|
||||
>p : Symbol(p, Decl(recursiveClassBaseType.ts, 2, 13))
|
||||
>T : Symbol(T, Decl(recursiveClassBaseType.ts, 2, 18))
|
||||
>fn : Symbol(fn, Decl(recursiveClassBaseType.ts, 2, 21))
|
||||
>T : Symbol(T, Decl(recursiveClassBaseType.ts, 2, 18))
|
||||
>T : Symbol(T, Decl(recursiveClassBaseType.ts, 2, 18))
|
||||
|
||||
declare const Base: <T>(val: T) => { new(): T };
|
||||
>Base : Symbol(Base, Decl(recursiveClassBaseType.ts, 4, 13))
|
||||
>T : Symbol(T, Decl(recursiveClassBaseType.ts, 4, 21))
|
||||
>val : Symbol(val, Decl(recursiveClassBaseType.ts, 4, 24))
|
||||
>T : Symbol(T, Decl(recursiveClassBaseType.ts, 4, 21))
|
||||
>T : Symbol(T, Decl(recursiveClassBaseType.ts, 4, 21))
|
||||
|
||||
class C extends Base({ x: p<C[]>(() => []) }) { }
|
||||
>C : Symbol(C, Decl(recursiveClassBaseType.ts, 4, 48))
|
||||
>Base : Symbol(Base, Decl(recursiveClassBaseType.ts, 4, 13))
|
||||
>x : Symbol(x, Decl(recursiveClassBaseType.ts, 6, 22))
|
||||
>p : Symbol(p, Decl(recursiveClassBaseType.ts, 2, 13))
|
||||
>C : Symbol(C, Decl(recursiveClassBaseType.ts, 4, 48))
|
||||
|
||||
// Repro from #44359
|
||||
|
||||
abstract class Base1 {
|
||||
>Base1 : Symbol(Base1, Decl(recursiveClassBaseType.ts, 6, 49))
|
||||
|
||||
abstract root(): Derived1;
|
||||
>root : Symbol(Base1.root, Decl(recursiveClassBaseType.ts, 10, 22))
|
||||
>Derived1 : Symbol(Derived1, Decl(recursiveClassBaseType.ts, 12, 1))
|
||||
}
|
||||
|
||||
class Derived1 extends class extends Base1 {
|
||||
>Derived1 : Symbol(Derived1, Decl(recursiveClassBaseType.ts, 12, 1))
|
||||
>Base1 : Symbol(Base1, Decl(recursiveClassBaseType.ts, 6, 49))
|
||||
|
||||
root() {
|
||||
>root : Symbol((Anonymous class).root, Decl(recursiveClassBaseType.ts, 14, 44))
|
||||
|
||||
return undefined as any;
|
||||
>undefined : Symbol(undefined)
|
||||
}
|
||||
}
|
||||
{ }
|
||||
|
||||
46
tests/baselines/reference/recursiveClassBaseType.types
Normal file
46
tests/baselines/reference/recursiveClassBaseType.types
Normal file
@@ -0,0 +1,46 @@
|
||||
=== tests/cases/compiler/recursiveClassBaseType.ts ===
|
||||
// Repro from #44281
|
||||
|
||||
declare const p: <T>(fn: () => T) => T;
|
||||
>p : <T>(fn: () => T) => T
|
||||
>fn : () => T
|
||||
|
||||
declare const Base: <T>(val: T) => { new(): T };
|
||||
>Base : <T>(val: T) => new () => T
|
||||
>val : T
|
||||
|
||||
class C extends Base({ x: p<C[]>(() => []) }) { }
|
||||
>C : C
|
||||
>Base({ x: p<C[]>(() => []) }) : { x: C[]; }
|
||||
>Base : <T>(val: T) => new () => T
|
||||
>{ x: p<C[]>(() => []) } : { x: C[]; }
|
||||
>x : C[]
|
||||
>p<C[]>(() => []) : C[]
|
||||
>p : <T>(fn: () => T) => T
|
||||
>() => [] : () => never[]
|
||||
>[] : never[]
|
||||
|
||||
// Repro from #44359
|
||||
|
||||
abstract class Base1 {
|
||||
>Base1 : Base1
|
||||
|
||||
abstract root(): Derived1;
|
||||
>root : () => Derived1
|
||||
}
|
||||
|
||||
class Derived1 extends class extends Base1 {
|
||||
>Derived1 : Derived1
|
||||
>class extends Base1 { root() { return undefined as any; }} : (Anonymous class)
|
||||
>Base1 : Base1
|
||||
|
||||
root() {
|
||||
>root : () => any
|
||||
|
||||
return undefined as any;
|
||||
>undefined as any : any
|
||||
>undefined : undefined
|
||||
}
|
||||
}
|
||||
{ }
|
||||
|
||||
23
tests/cases/compiler/recursiveClassBaseType.ts
Normal file
23
tests/cases/compiler/recursiveClassBaseType.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
// @strict: true
|
||||
// @declaration: true
|
||||
|
||||
// Repro from #44281
|
||||
|
||||
declare const p: <T>(fn: () => T) => T;
|
||||
|
||||
declare const Base: <T>(val: T) => { new(): T };
|
||||
|
||||
class C extends Base({ x: p<C[]>(() => []) }) { }
|
||||
|
||||
// Repro from #44359
|
||||
|
||||
abstract class Base1 {
|
||||
abstract root(): Derived1;
|
||||
}
|
||||
|
||||
class Derived1 extends class extends Base1 {
|
||||
root() {
|
||||
return undefined as any;
|
||||
}
|
||||
}
|
||||
{ }
|
||||
Reference in New Issue
Block a user